<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Interactive BOM for KiCAD</title>
  <style type="text/css">
:root {
  --pcb-edge-color: black;
  --pad-color: #878787;
  --pad-hole-color: #CCCCCC;
  --pad-color-highlight: #D04040;
  --pin1-outline-color: #ffb629;
  --pin1-outline-color-highlight: #b4ff03;
  --silkscreen-edge-color: #aa4;
  --silkscreen-polygon-color: #4aa;
  --silkscreen-text-color: #4aa;
  --fabrication-edge-color: #907651;
  --fabrication-polygon-color: #907651;
  --fabrication-text-color: #a27c24;
  --track-color: #def5f1;
  --track-color-highlight: #D04040;
  --zone-color: #def5f1;
  --zone-color-highlight: #d0404080;
}

html, body {
  margin: 0px;
  height: 100%;
  font-family: Verdana, sans-serif;
}

.dark.topmostdiv {
  --pcb-edge-color: #eee;
  --pad-color: #808080;
  --pin1-outline-color: #ffa800;
  --pin1-outline-color-highlight: #ccff00;
  --track-color: #42524f;
  --zone-color: #42524f;
  background-color: #252c30;
  color: #eee;
}

button {
  background-color: #eee;
  border: 1px solid #888;
  color: black;
  height: 44px;
  width: 44px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 14px;
  font-weight: bolder;
}

.dark button {
  /* This will be inverted */
  background-color: #c3b7b5;
}

button.depressed {
  background-color: #0a0;
  color: white;
}

.dark button.depressed {
  /* This will be inverted */
  background-color: #b3b;
}

button:focus {
  outline: 0;
}

button#tb-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8.47 8.47'%3E%3Crect transform='translate(0 -288.53)' ry='1.17' y='288.8' x='.27' height='7.94' width='7.94' fill='%23f9f9f9'/%3E%3Cg transform='translate(0 -288.53)'%3E%3Crect width='7.94' height='7.94' x='.27' y='288.8' ry='1.17' fill='none' stroke='%23000' stroke-width='.4' stroke-linejoin='round'/%3E%3Cpath d='M1.32 290.12h5.82M1.32 291.45h5.82' fill='none' stroke='%23000' stroke-width='.4'/%3E%3Cpath d='M4.37 292.5v4.23M.26 292.63H8.2' fill='none' stroke='%23000' stroke-width='.3'/%3E%3Ctext font-weight='700' font-size='3.17' font-family='sans-serif'%3E%3Ctspan x='1.35' y='295.73'%3EF%3C/tspan%3E%3Ctspan x='5.03' y='295.68'%3EB%3C/tspan%3E%3C/text%3E%3C/g%3E%3C/svg%3E%0A");
}

button#lr-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8.47 8.47'%3E%3Crect transform='translate(0 -288.53)' ry='1.17' y='288.8' x='.27' height='7.94' width='7.94' fill='%23f9f9f9'/%3E%3Cg transform='translate(0 -288.53)'%3E%3Crect width='7.94' height='7.94' x='.27' y='288.8' ry='1.17' fill='none' stroke='%23000' stroke-width='.4' stroke-linejoin='round'/%3E%3Cpath d='M1.06 290.12H3.7m-2.64 1.33H3.7m-2.64 1.32H3.7m-2.64 1.3H3.7m-2.64 1.33H3.7' fill='none' stroke='%23000' stroke-width='.4'/%3E%3Cpath d='M4.37 288.8v7.94m0-4.11h3.96' fill='none' stroke='%23000' stroke-width='.3'/%3E%3Ctext font-weight='700' font-size='3.17' font-family='sans-serif'%3E%3Ctspan x='5.11' y='291.96'%3EF%3C/tspan%3E%3Ctspan x='5.03' y='295.68'%3EB%3C/tspan%3E%3C/text%3E%3C/g%3E%3C/svg%3E%0A");
}

button#bom-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8.47 8.47'%3E%3Crect transform='translate(0 -288.53)' ry='1.17' y='288.8' x='.27' height='7.94' width='7.94' fill='%23f9f9f9'/%3E%3Cg transform='translate(0 -288.53)' fill='none' stroke='%23000' stroke-width='.4'%3E%3Crect width='7.94' height='7.94' x='.27' y='288.8' ry='1.17' stroke-linejoin='round'/%3E%3Cpath d='M1.59 290.12h5.29M1.59 291.45h5.33M1.59 292.75h5.33M1.59 294.09h5.33M1.59 295.41h5.33'/%3E%3C/g%3E%3C/svg%3E");
}

button#bom-grouped-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cg stroke='%23000' stroke-linejoin='round' class='layer'%3E%3Crect width='29' height='29' x='1.5' y='1.5' stroke-width='2' fill='%23fff' rx='5' ry='5'/%3E%3Cpath stroke-linecap='square' stroke-width='2' d='M6 10h4m4 0h5m4 0h3M6.1 22h3m3.9 0h5m4 0h4m-16-8h4m4 0h4'/%3E%3Cpath stroke-linecap='null' d='M5 17.5h22M5 26.6h22M5 5.5h22'/%3E%3C/g%3E%3C/svg%3E");
}

button#bom-ungrouped-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cg stroke='%23000' stroke-linejoin='round' class='layer'%3E%3Crect width='29' height='29' x='1.5' y='1.5' stroke-width='2' fill='%23fff' rx='5' ry='5'/%3E%3Cpath stroke-linecap='square' stroke-width='2' d='M6 10h4m-4 8h3m-3 8h4'/%3E%3Cpath stroke-linecap='null' d='M5 13.5h22m-22 8h22M5 5.5h22'/%3E%3C/g%3E%3C/svg%3E");
}

button#bom-netlist-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cg fill='none' stroke='%23000' class='layer'%3E%3Crect width='29' height='29' x='1.5' y='1.5' stroke-width='2' fill='%23fff' rx='5' ry='5'/%3E%3Cpath stroke-width='2' d='M6 26l6-6v-8m13.8-6.3l-6 6v8'/%3E%3Ccircle cx='11.8' cy='9.5' r='2.8' stroke-width='2'/%3E%3Ccircle cx='19.8' cy='22.8' r='2.8' stroke-width='2'/%3E%3C/g%3E%3C/svg%3E");
}

button#copy {
  background-image: url("data:image/svg+xml,%3Csvg height='48' viewBox='0 0 48 48' width='48' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0h48v48h-48z' fill='none'/%3E%3Cpath d='M32 2h-24c-2.21 0-4 1.79-4 4v28h4v-28h24v-4zm6 8h-22c-2.21 0-4 1.79-4 4v28c0 2.21 1.79 4 4 4h22c2.21 0 4-1.79 4-4v-28c0-2.21-1.79-4-4-4zm0 32h-22v-28h22v28z'/%3E%3C/svg%3E");
  background-position: 6px 6px;
  background-repeat: no-repeat;
  background-size: 26px 26px;
  border-radius: 6px;
  height: 40px;
  width: 40px;
  margin: 10px 5px;
}

button#copy:active {
    box-shadow: inset 0px 0px 5px #6c6c6c;
}

textarea.clipboard-temp {
  position: fixed;
  top: 0;
  left: 0;
  width: 2em;
  height: 2em;
  padding: 0;
  border: None;
  outline: None;
  box-shadow: None;
  background: transparent;
}

.left-most-button {
  border-right: 0;
  border-top-left-radius: 6px;
  border-bottom-left-radius: 6px;
}

.middle-button {
  border-right: 0;
}

.right-most-button {
  border-top-right-radius: 6px;
  border-bottom-right-radius: 6px;
}

.button-container {
  font-size: 0;
  margin: 10px 10px 10px 0px;
}

.dark .button-container {
  filter: invert(1);
}

.button-container button {
  background-size: 32px 32px;
  background-position: 5px 5px;
  background-repeat: no-repeat;
}

@media print {
  .hideonprint {
    display: none;
  }
}

canvas {
  cursor: crosshair;
}

canvas:active {
  cursor: grabbing;
}

.fileinfo {
  width: 100%;
  max-width: 1000px;
  border: none;
  padding: 5px;
}

.fileinfo .title {
  font-size: 20pt;
  font-weight: bold;
}

.fileinfo td {
  overflow: hidden;
  white-space: nowrap;
  max-width: 1px;
  width: 50%;
  text-overflow: ellipsis;
}

.bom {
  border-collapse: collapse;
  font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace;
  font-size: 10pt;
  table-layout: fixed;
  width: 100%;
  margin-top: 1px;
}

.bom th, .bom td {
  border: 1px solid black;
  padding: 5px;
  word-wrap: break-word;
  text-align: center;
  position: relative;
}

.dark .bom th, .dark .bom td {
  border: 1px solid #777;
}

.bom th {
  background-color: #CCCCCC;
  background-clip: padding-box;
}

.dark .bom th {
  background-color: #3b4749;
}

.bom tr.highlighted:nth-child(n) {
  background-color: #cfc;
}

.dark .bom tr.highlighted:nth-child(n) {
  background-color: #226022;
}

.bom tr:nth-child(even) {
  background-color: #f2f2f2;
}

.dark .bom tr:nth-child(even) {
  background-color: #313b40;
}

.bom tr.checked {
  color: #aaa;
}

.dark .bom tr.checked {
  color: #666;
}

.bom tr {
  transition: background-color 0.2s;
}

.bom .numCol {
  width: 25px;
}

.bom .Description {
  width: 10%;
}

.bom .Part {
  width: 10%;
}

.bom .Value {
  width: 15%;
}

.bom .Quantity {
  width: 65px;
}

.bom th .sortmark {
  position: absolute;
  right: 1px;
  top: 1px;
  margin-top: -5px;
  border-width: 5px;
  border-style: solid;
  border-color: transparent transparent #221 transparent;
  transform-origin: 50% 85%;
  transition: opacity 0.2s, transform 0.4s;
}

.dark .bom th .sortmark {
  filter: invert(1);
}

.bom th .sortmark.none {
  opacity: 0;
}

.bom th .sortmark.desc {
  transform: rotate(180deg);
}

.bom th:hover .sortmark.none {
  opacity: 0.5;
}

.bom .bom-checkbox {
  width: 30px;
  position: relative;
  user-select: none;
  -moz-user-select: none;
}

.bom .bom-checkbox:before {
  content: "";
  position: absolute;
  border-width: 15px;
  border-style: solid;
  border-color: #51829f transparent transparent transparent;
  visibility: hidden;
  top: -15px;
}

.bom .bom-checkbox:after {
  content: "Double click to set/unset all";
  position: absolute;
  color: white;
  top: -35px;
  left: -26px;
  background: #51829f;
  padding: 5px 15px;
  border-radius: 8px;
  white-space: nowrap;
  visibility: hidden;
}

.bom .bom-checkbox:hover:before, .bom .bom-checkbox:hover:after {
  visibility: visible;
  transition: visibility 0.2s linear 1s;
}

.split {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  overflow-y: auto;
  overflow-x: hidden;
  background-color: inherit;
}

.split.split-horizontal, .gutter.gutter-horizontal {
  height: 100%;
  float: left;
}

.gutter {
  background-color: #ddd;
  background-repeat: no-repeat;
  background-position: 50%;
  transition: background-color 0.3s;
}

.dark .gutter {
  background-color: #777;
}

.gutter.gutter-horizontal {
  background-image: url('');
  cursor: ew-resize;
  width: 5px;
}

.gutter.gutter-vertical {
  background-image: url('');
  cursor: ns-resize;
  height: 5px;
}

.searchbox {
  float: left;
  height: 40px;
  margin: 10px 5px;
  padding: 12px 32px;
  font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace;
  font-size: 18px;
  box-sizing: border-box;
  border: 1px solid #888;
  border-radius: 6px;
  outline: none;
  background-color: #eee;
  transition: background-color 0.2s, border 0.2s;
  background-image: url('');
  background-position: 10px 10px;
  background-repeat: no-repeat;
}

.dark .searchbox {
  background-color: #111;
  color: #eee;
}

.searchbox::placeholder {
  color: #ccc;
}

.dark .searchbox::placeholder {
  color: #666;
}

.filter {
  width: calc(60% - 64px);
}

.reflookup {
  width: calc(40% - 10px);
}

input[type=text]:focus {
  background-color: white;
  border: 1px solid #333;
}

.dark input[type=text]:focus {
  background-color: #333;
  border: 1px solid #ccc;
}

mark.highlight {
  background-color: #5050ff;
  color: #fff;
  padding: 2px;
  border-radius: 6px;
}

.dark mark.highlight {
  background-color: #76a6da;
  color: #111;
}

.menubtn {
  background-color: white;
  border: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='36' height='36' viewBox='0 0 20 20'%3E%3Cpath fill='none' d='M0 0h20v20H0V0z'/%3E%3Cpath d='M15.95 10.78c.03-.25.05-.51.05-.78s-.02-.53-.06-.78l1.69-1.32c.15-.12.19-.34.1-.51l-1.6-2.77c-.1-.18-.31-.24-.49-.18l-1.99.8c-.42-.32-.86-.58-1.35-.78L12 2.34c-.03-.2-.2-.34-.4-.34H8.4c-.2 0-.36.14-.39.34l-.3 2.12c-.49.2-.94.47-1.35.78l-1.99-.8c-.18-.07-.39 0-.49.18l-1.6 2.77c-.1.18-.06.39.1.51l1.69 1.32c-.04.25-.07.52-.07.78s.02.53.06.78L2.37 12.1c-.15.12-.19.34-.1.51l1.6 2.77c.1.18.31.24.49.18l1.99-.8c.42.32.86.58 1.35.78l.3 2.12c.04.2.2.34.4.34h3.2c.2 0 .37-.14.39-.34l.3-2.12c.49-.2.94-.47 1.35-.78l1.99.8c.18.07.39 0 .49-.18l1.6-2.77c.1-.18.06-.39-.1-.51l-1.67-1.32zM10 13c-1.65 0-3-1.35-3-3s1.35-3 3-3 3 1.35 3 3-1.35 3-3 3z'/%3E%3C/svg%3E%0A");
  background-position: center;
  background-repeat: no-repeat;
}

.statsbtn {
  background-color: white;
  border: none;
  background-image: url("data:image/svg+xml,%3Csvg width='36' height='36' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 6h28v24H4V6zm0 8h28v8H4m9-16v24h10V5.8' fill='none' stroke='%23000' stroke-width='2'/%3E%3C/svg%3E");
  background-position: center;
  background-repeat: no-repeat;
}

.iobtn {
  background-color: white;
  border: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='36' height='36'%3E%3Cpath fill='none' stroke='%23000' stroke-width='2' d='M3 33v-7l6.8-7h16.5l6.7 7v7H3zM3.2 26H33M21 9l5-5.9 5 6h-2.5V15h-5V9H21zm-4.9 0l-5 6-5-6h2.5V3h5v6h2.5z'/%3E%3Cpath fill='none' stroke='%23000' d='M6.1 29.5H10'/%3E%3C/svg%3E");
  background-position: center;
  background-repeat: no-repeat;
}

.dark .statsbtn, .dark .savebtn, .dark .menubtn, .dark .iobtn {
  filter: invert(1);
}

.flexbox {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}

.savebtn {
  background-color: #d6d6d6;
  width: auto;
  height: 30px;
  flex-grow: 1;
  margin: 5px;
  border-radius: 4px;
}

.savebtn:active {
  background-color: #0a0;
  color: white;
}

.dark .savebtn:active {
  /* This will be inverted */
  background-color: #b3b;
}

.stats {
  border-collapse: collapse;
  font-size: 12pt;
  table-layout: fixed;
  width: 100%;
  min-width: 450px;
}

.dark .stats td {
  border: 1px solid #bbb;
}

.stats td {
  border: 1px solid black;
  padding: 5px;
  word-wrap: break-word;
  text-align: center;
  position: relative;
}

#checkbox-stats div {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

#checkbox-stats .bar {
  background-color: rgba(28, 251, 0, 0.6);
}

.menu {
  position: relative;
  display: inline-block;
  margin: 10px 10px 10px 0px;
}

.menu-content {
  display: none;
  position: absolute;
  background-color: white;
  right: 0;
  min-width: 300px;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  z-index: 100;
  padding: 8px;
}

.dark .menu-content {
  background-color: #111;
}

.menu:hover .menu-content {
  display: block;
}

.menu:hover .menubtn, .menu:hover .iobtn, .menu:hover .statsbtn {
  background-color: #eee;
}

.menu-label {
  display: inline-block;
  padding: 8px;
  border: 1px solid #ccc;
  border-top: 0;
  width: calc(100% - 18px);
}

.menu-label-top {
  border-top: 1px solid #ccc;
}

.menu-textbox {
  float: left;
  height: 24px;
  margin: 10px 5px;
  padding: 5px 5px;
  font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace;
  font-size: 14px;
  box-sizing: border-box;
  border: 1px solid #888;
  border-radius: 4px;
  outline: none;
  background-color: #eee;
  transition: background-color 0.2s, border 0.2s;
  width: calc(100% - 10px);
}

.menu-textbox.invalid, .dark .menu-textbox.invalid {
  color: red;
}

.dark .menu-textbox {
  background-color: #222;
  color: #eee;
}

.radio-container {
  margin: 4px;
}

.topmostdiv {
  width: 100%;
  height: 100%;
  background-color: white;
  transition: background-color 0.3s;
}

#top {
  height: 78px;
  border-bottom: 2px solid black;
}

.dark #top {
  border-bottom: 2px solid #ccc;
}

#dbg {
  display: block;
}

::-webkit-scrollbar {
  width: 8px;
}

::-webkit-scrollbar-track {
  background: #aaa;
}

::-webkit-scrollbar-thumb {
  background: #666;
  border-radius: 3px;
}

::-webkit-scrollbar-thumb:hover {
  background: #555;
}

.slider {
  -webkit-appearance: none;
  width: 100%;
  margin: 3px 0;
  padding: 0;
  outline: none;
  opacity: 0.7;
  -webkit-transition: .2s;
  transition: opacity .2s;
  border-radius: 3px;
}

.slider:hover {
  opacity: 1;
}

.slider:focus {
  outline: none;
}

.slider::-webkit-slider-runnable-track {
  -webkit-appearance: none;
  width: 100%;
  height: 8px;
  background: #d3d3d3;
  border-radius: 3px;
  border: none;
}

.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: #0a0;
  cursor: pointer;
  margin-top: -4px;
}

.dark .slider::-webkit-slider-thumb {
  background: #3d3;
}

.slider::-moz-range-thumb {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: #0a0;
  cursor: pointer;
}

.slider::-moz-range-track {
  height: 8px;
  background: #d3d3d3;
  border-radius: 3px;
}

.dark .slider::-moz-range-thumb {
  background: #3d3;
}

.slider::-ms-track {
  width: 100%;
  height: 8px;
  border-width: 3px 0;
  background: transparent;
  border-color: transparent;
  color: transparent;
  transition: opacity .2s;
}

.slider::-ms-fill-lower {
  background: #d3d3d3;
  border: none;
  border-radius: 3px;
}

.slider::-ms-fill-upper {
  background: #d3d3d3;
  border: none;
  border-radius: 3px;
}

.slider::-ms-thumb {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: #0a0;
  cursor: pointer;
  margin: 0;
}

.shameless-plug {
  font-size: 0.8em;
  text-align: center;
  display: block;
}

a {
  color: #0278a4;
}

.dark a {
  color: #00b9fd;
}

#frontcanvas, #backcanvas {
    touch-action: none;
}

 
  </style>
  <script type="text/javascript" >
///////////////////////////////////////////////
/*
  Split.js - v1.3.5
  MIT License
  https://github.com/nathancahill/Split.js
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Split=t()}(this,function(){"use strict";var e=window,t=e.document,n="addEventListener",i="removeEventListener",r="getBoundingClientRect",s=function(){return!1},o=e.attachEvent&&!e[n],a=["","-webkit-","-moz-","-o-"].filter(function(e){var n=t.createElement("div");return n.style.cssText="width:"+e+"calc(9px)",!!n.style.length}).shift()+"calc",l=function(e){return"string"==typeof e||e instanceof String?t.querySelector(e):e};return function(u,c){function z(e,t,n){var i=A(y,t,n);Object.keys(i).forEach(function(t){return e.style[t]=i[t]})}function h(e,t){var n=B(y,t);Object.keys(n).forEach(function(t){return e.style[t]=n[t]})}function f(e){var t=E[this.a],n=E[this.b],i=t.size+n.size;t.size=e/this.size*i,n.size=i-e/this.size*i,z(t.element,t.size,this.aGutterSize),z(n.element,n.size,this.bGutterSize)}function m(e){var t;this.dragging&&((t="touches"in e?e.touches[0][b]-this.start:e[b]-this.start)<=E[this.a].minSize+M+this.aGutterSize?t=E[this.a].minSize+this.aGutterSize:t>=this.size-(E[this.b].minSize+M+this.bGutterSize)&&(t=this.size-(E[this.b].minSize+this.bGutterSize)),f.call(this,t),c.onDrag&&c.onDrag())}function g(){var e=E[this.a].element,t=E[this.b].element;this.size=e[r]()[y]+t[r]()[y]+this.aGutterSize+this.bGutterSize,this.start=e[r]()[G]}function d(){var t=this,n=E[t.a].element,r=E[t.b].element;t.dragging&&c.onDragEnd&&c.onDragEnd(),t.dragging=!1,e[i]("mouseup",t.stop),e[i]("touchend",t.stop),e[i]("touchcancel",t.stop),t.parent[i]("mousemove",t.move),t.parent[i]("touchmove",t.move),delete t.stop,delete t.move,n[i]("selectstart",s),n[i]("dragstart",s),r[i]("selectstart",s),r[i]("dragstart",s),n.style.userSelect="",n.style.webkitUserSelect="",n.style.MozUserSelect="",n.style.pointerEvents="",r.style.userSelect="",r.style.webkitUserSelect="",r.style.MozUserSelect="",r.style.pointerEvents="",t.gutter.style.cursor="",t.parent.style.cursor=""}function S(t){var i=this,r=E[i.a].element,o=E[i.b].element;!i.dragging&&c.onDragStart&&c.onDragStart(),t.preventDefault(),i.dragging=!0,i.move=m.bind(i),i.stop=d.bind(i),e[n]("mouseup",i.stop),e[n]("touchend",i.stop),e[n]("touchcancel",i.stop),i.parent[n]("mousemove",i.move),i.parent[n]("touchmove",i.move),r[n]("selectstart",s),r[n]("dragstart",s),o[n]("selectstart",s),o[n]("dragstart",s),r.style.userSelect="none",r.style.webkitUserSelect="none",r.style.MozUserSelect="none",r.style.pointerEvents="none",o.style.userSelect="none",o.style.webkitUserSelect="none",o.style.MozUserSelect="none",o.style.pointerEvents="none",i.gutter.style.cursor=j,i.parent.style.cursor=j,g.call(i)}function v(e){e.forEach(function(t,n){if(n>0){var i=F[n-1],r=E[i.a],s=E[i.b];r.size=e[n-1],s.size=t,z(r.element,r.size,i.aGutterSize),z(s.element,s.size,i.bGutterSize)}})}function p(){F.forEach(function(e){e.parent.removeChild(e.gutter),E[e.a].element.style[y]="",E[e.b].element.style[y]=""})}void 0===c&&(c={});var y,b,G,E,w=l(u[0]).parentNode,D=e.getComputedStyle(w).flexDirection,U=c.sizes||u.map(function(){return 100/u.length}),k=void 0!==c.minSize?c.minSize:100,x=Array.isArray(k)?k:u.map(function(){return k}),L=void 0!==c.gutterSize?c.gutterSize:10,M=void 0!==c.snapOffset?c.snapOffset:30,O=c.direction||"horizontal",j=c.cursor||("horizontal"===O?"ew-resize":"ns-resize"),C=c.gutter||function(e,n){var i=t.createElement("div");return i.className="gutter gutter-"+n,i},A=c.elementStyle||function(e,t,n){var i={};return"string"==typeof t||t instanceof String?i[e]=t:i[e]=o?t+"%":a+"("+t+"% - "+n+"px)",i},B=c.gutterStyle||function(e,t){return n={},n[e]=t+"px",n;var n};"horizontal"===O?(y="width","clientWidth",b="clientX",G="left","paddingLeft"):"vertical"===O&&(y="height","clientHeight",b="clientY",G="top","paddingTop");var F=[];return E=u.map(function(e,t){var i,s={element:l(e),size:U[t],minSize:x[t]};if(t>0&&(i={a:t-1,b:t,dragging:!1,isFirst:1===t,isLast:t===u.length-1,direction:O,parent:w},i.aGutterSize=L,i.bGutterSize=L,i.isFirst&&(i.aGutterSize=L/2),i.isLast&&(i.bGutterSize=L/2),"row-reverse"===D||"column-reverse"===D)){var a=i.a;i.a=i.b,i.b=a}if(!o&&t>0){var c=C(t,O);h(c,L),c[n]("mousedown",S.bind(i)),c[n]("touchstart",S.bind(i)),w.insertBefore(c,s.element),i.gutter=c}0===t||t===u.length-1?z(s.element,s.size,L/2):z(s.element,s.size,L);var f=s.element[r]()[y];return f<s.minSize&&(s.minSize=f),t>0&&F.push(i),s}),o?{setSizes:v,destroy:p}:{setSizes:v,getSizes:function(){return E.map(function(e){return e.size})},collapse:function(e){if(e===F.length){var t=F[e-1];g.call(t),o||f.call(t,t.size-t.bGutterSize)}else{var n=F[e];g.call(n),o||f.call(n,n.aGutterSize)}},destroy:p}}});

///////////////////////////////////////////////

///////////////////////////////////////////////
// Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net>
// This work is free. You can redistribute it and/or modify it
// under the terms of the WTFPL, Version 2
// For more information see LICENSE.txt or http://www.wtfpl.net/
//
// For more information, the home page:
// http://pieroxy.net/blog/pages/lz-string/testing.html
//
// LZ-based compression algorithm, version 1.4.4
var LZString=function(){var o=String.fromCharCode,i={};var n={decompressFromBase64:function(o){return null==o?"":""==o?null:n._decompress(o.length,32,function(n){return function(o,n){if(!i[o]){i[o]={};for(var t=0;t<o.length;t++)i[o][o.charAt(t)]=t}return i[o][n]}("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",o.charAt(n))})},_decompress:function(i,n,t){var r,e,a,s,p,u,l,f=[],c=4,d=4,h=3,v="",g=[],m={val:t(0),position:n,index:1};for(r=0;r<3;r+=1)f[r]=r;for(a=0,p=Math.pow(2,2),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;switch(a){case 0:for(a=0,p=Math.pow(2,8),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;l=o(a);break;case 1:for(a=0,p=Math.pow(2,16),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;l=o(a);break;case 2:return""}for(f[3]=l,e=l,g.push(l);;){if(m.index>i)return"";for(a=0,p=Math.pow(2,h),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;switch(l=a){case 0:for(a=0,p=Math.pow(2,8),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;f[d++]=o(a),l=d-1,c--;break;case 1:for(a=0,p=Math.pow(2,16),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;f[d++]=o(a),l=d-1,c--;break;case 2:return g.join("")}if(0==c&&(c=Math.pow(2,h),h++),f[l])v=f[l];else{if(l!==d)return null;v=e+e.charAt(0)}g.push(v),f[d++]=e+v.charAt(0),e=v,0==--c&&(c=Math.pow(2,h),h++)}}};return n}();"function"==typeof define&&define.amd?define(function(){return LZString}):"undefined"!=typeof module&&null!=module?module.exports=LZString:"undefined"!=typeof angular&&null!=angular&&angular.module("LZString",[]).factory("LZString",function(){return LZString});
///////////////////////////////////////////////

///////////////////////////////////////////////
/*!
 * PEP v0.4.3 | https://github.com/jquery/PEP
 * Copyright jQuery Foundation and other contributors | http://jquery.org/license
 */
! function (a, b) {
  "object" == typeof exports && "undefined" != typeof module ? module.exports = b() : "function" == typeof define && define.amd ? define(b) : a.PointerEventsPolyfill = b()
}(this, function () {
  "use strict";

  function a(a, b) {
    b = b || Object.create(null);
    var c = document.createEvent("Event");
    c.initEvent(a, b.bubbles || !1, b.cancelable || !1);
    for (var d, e = 2; e < m.length; e++) d = m[e], c[d] = b[d] || n[e];
    c.buttons = b.buttons || 0;
    var f = 0;
    return f = b.pressure && c.buttons ? b.pressure : c.buttons ? .5 : 0, c.x = c.clientX, c.y = c.clientY, c.pointerId = b.pointerId || 0, c.width = b.width || 0, c.height = b.height || 0, c.pressure = f, c.tiltX = b.tiltX || 0, c.tiltY = b.tiltY || 0, c.twist = b.twist || 0, c.tangentialPressure = b.tangentialPressure || 0, c.pointerType = b.pointerType || "", c.hwTimestamp = b.hwTimestamp || 0, c.isPrimary = b.isPrimary || !1, c
  }

  function b() {
    this.array = [], this.size = 0
  }

  function c(a, b, c, d) {
    this.addCallback = a.bind(d), this.removeCallback = b.bind(d), this.changedCallback = c.bind(d), A && (this.observer = new A(this.mutationWatcher.bind(this)))
  }

  function d(a) {
    return "body /shadow-deep/ " + e(a)
  }

  function e(a) {
    return '[touch-action="' + a + '"]'
  }

  function f(a) {
    return "{ -ms-touch-action: " + a + "; touch-action: " + a + "; }"
  }

  function g() {
    if (F) {
      D.forEach(function (a) {
        String(a) === a ? (E += e(a) + f(a) + "\n", G && (E += d(a) + f(a) + "\n")) : (E += a.selectors.map(e) + f(a.rule) + "\n", G && (E += a.selectors.map(d) + f(a.rule) + "\n"))
      });
      var a = document.createElement("style");
      a.textContent = E, document.head.appendChild(a)
    }
  }

  function h() {
    if (!window.PointerEvent) {
      if (window.PointerEvent = a, window.navigator.msPointerEnabled) {
        var b = window.navigator.msMaxTouchPoints;
        Object.defineProperty(window.navigator, "maxTouchPoints", {
          value: b,
          enumerable: !0
        }), u.registerSource("ms", _)
      } else Object.defineProperty(window.navigator, "maxTouchPoints", {
        value: 0,
        enumerable: !0
      }), u.registerSource("mouse", N), void 0 !== window.ontouchstart && u.registerSource("touch", V);
      u.register(document)
    }
  }

  function i(a) {
    if (!u.pointermap.has(a)) {
      var b = new Error("InvalidPointerId");
      throw b.name = "InvalidPointerId", b
    }
  }

  function j(a) {
    for (var b = a.parentNode; b && b !== a.ownerDocument;) b = b.parentNode;
    if (!b) {
      var c = new Error("InvalidStateError");
      throw c.name = "InvalidStateError", c
    }
  }

  function k(a) {
    var b = u.pointermap.get(a);
    return 0 !== b.buttons
  }

  function l() {
    window.Element && !Element.prototype.setPointerCapture && Object.defineProperties(Element.prototype, {
      setPointerCapture: {
        value: W
      },
      releasePointerCapture: {
        value: X
      },
      hasPointerCapture: {
        value: Y
      }
    })
  }
  var m = ["bubbles", "cancelable", "view", "detail", "screenX", "screenY", "clientX", "clientY", "ctrlKey", "altKey", "shiftKey", "metaKey", "button", "relatedTarget", "pageX", "pageY"],
    n = [!1, !1, null, null, 0, 0, 0, 0, !1, !1, !1, !1, 0, null, 0, 0],
    o = window.Map && window.Map.prototype.forEach,
    p = o ? Map : b;
  b.prototype = {
    set: function (a, b) {
      return void 0 === b ? this["delete"](a) : (this.has(a) || this.size++, void(this.array[a] = b))
    },
    has: function (a) {
      return void 0 !== this.array[a]
    },
    "delete": function (a) {
      this.has(a) && (delete this.array[a], this.size--)
    },
    get: function (a) {
      return this.array[a]
    },
    clear: function () {
      this.array.length = 0, this.size = 0
    },
    forEach: function (a, b) {
      return this.array.forEach(function (c, d) {
        a.call(b, c, d, this)
      }, this)
    }
  };
  var q = ["bubbles", "cancelable", "view", "detail", "screenX", "screenY", "clientX", "clientY", "ctrlKey", "altKey", "shiftKey", "metaKey", "button", "relatedTarget", "buttons", "pointerId", "width", "height", "pressure", "tiltX", "tiltY", "pointerType", "hwTimestamp", "isPrimary", "type", "target", "currentTarget", "which", "pageX", "pageY", "timeStamp"],
    r = [!1, !1, null, null, 0, 0, 0, 0, !1, !1, !1, !1, 0, null, 0, 0, 0, 0, 0, 0, 0, "", 0, !1, "", null, null, 0, 0, 0, 0],
    s = {
      pointerover: 1,
      pointerout: 1,
      pointerenter: 1,
      pointerleave: 1
    },
    t = "undefined" != typeof SVGElementInstance,
    u = {
      pointermap: new p,
      eventMap: Object.create(null),
      captureInfo: Object.create(null),
      eventSources: Object.create(null),
      eventSourceList: [],
      registerSource: function (a, b) {
        var c = b,
          d = c.events;
        d && (d.forEach(function (a) {
          c[a] && (this.eventMap[a] = c[a].bind(c))
        }, this), this.eventSources[a] = c, this.eventSourceList.push(c))
      },
      register: function (a) {
        for (var b, c = this.eventSourceList.length, d = 0; d < c && (b = this.eventSourceList[d]); d++)
          b.register.call(b, a)
      },
      unregister: function (a) {
        for (var b, c = this.eventSourceList.length, d = 0; d < c && (b = this.eventSourceList[d]); d++)
          b.unregister.call(b, a)
      },
      contains: function (a, b) {
        try {
          return a.contains(b)
        } catch (c) {
          return !1
        }
      },
      down: function (a) {
        a.bubbles = !0, this.fireEvent("pointerdown", a)
      },
      move: function (a) {
        a.bubbles = !0, this.fireEvent("pointermove", a)
      },
      up: function (a) {
        a.bubbles = !0, this.fireEvent("pointerup", a)
      },
      enter: function (a) {
        a.bubbles = !1, this.fireEvent("pointerenter", a)
      },
      leave: function (a) {
        a.bubbles = !1, this.fireEvent("pointerleave", a)
      },
      over: function (a) {
        a.bubbles = !0, this.fireEvent("pointerover", a)
      },
      out: function (a) {
        a.bubbles = !0, this.fireEvent("pointerout", a)
      },
      cancel: function (a) {
        a.bubbles = !0, this.fireEvent("pointercancel", a)
      },
      leaveOut: function (a) {
        this.out(a), this.propagate(a, this.leave, !1)
      },
      enterOver: function (a) {
        this.over(a), this.propagate(a, this.enter, !0)
      },
      eventHandler: function (a) {
        if (!a._handledByPE) {
          var b = a.type,
            c = this.eventMap && this.eventMap[b];
          c && c(a), a._handledByPE = !0
        }
      },
      listen: function (a, b) {
        b.forEach(function (b) {
          this.addEvent(a, b)
        }, this)
      },
      unlisten: function (a, b) {
        b.forEach(function (b) {
          this.removeEvent(a, b)
        }, this)
      },
      addEvent: function (a, b) {
        a.addEventListener(b, this.boundHandler)
      },
      removeEvent: function (a, b) {
        a.removeEventListener(b, this.boundHandler)
      },
      makeEvent: function (b, c) {
        this.captureInfo[c.pointerId] && (c.relatedTarget = null);
        var d = new a(b, c);
        return c.preventDefault && (d.preventDefault = c.preventDefault), d._target = d._target || c.target, d
      },
      fireEvent: function (a, b) {
        var c = this.makeEvent(a, b);
        return this.dispatchEvent(c)
      },
      cloneEvent: function (a) {
        for (var b, c = Object.create(null), d = 0; d < q.length; d++) b = q[d], c[b] = a[b] || r[d], !t || "target" !== b && "relatedTarget" !== b || c[b] instanceof SVGElementInstance && (c[b] = c[b].correspondingUseElement);
        return a.preventDefault && (c.preventDefault = function () {
          a.preventDefault()
        }), c
      },
      getTarget: function (a) {
        var b = this.captureInfo[a.pointerId];
        return b ? a._target !== b && a.type in s ? void 0 : b : a._target
      },
      propagate: function (a, b, c) {
        for (var d = a.target, e = []; d !== document && !d.contains(a.relatedTarget);)
          if (e.push(d), d = d.parentNode, !d) return;
        c && e.reverse(), e.forEach(function (c) {
          a.target = c, b.call(this, a)
        }, this)
      },
      setCapture: function (b, c, d) {
        this.captureInfo[b] && this.releaseCapture(b, d), this.captureInfo[b] = c, this.implicitRelease = this.releaseCapture.bind(this, b, d), document.addEventListener("pointerup", this.implicitRelease), document.addEventListener("pointercancel", this.implicitRelease);
        var e = new a("gotpointercapture");
        e.pointerId = b, e._target = c, d || this.asyncDispatchEvent(e)
      },
      releaseCapture: function (b, c) {
        var d = this.captureInfo[b];
        if (d) {
          this.captureInfo[b] = void 0, document.removeEventListener("pointerup", this.implicitRelease), document.removeEventListener("pointercancel", this.implicitRelease);
          var e = new a("lostpointercapture");
          e.pointerId = b, e._target = d, c || this.asyncDispatchEvent(e)
        }
      },
      dispatchEvent: /*scope.external.dispatchEvent || */ function (a) {
        var b = this.getTarget(a);
        if (b) return b.dispatchEvent(a)
      },
      asyncDispatchEvent: function (a) {
        requestAnimationFrame(this.dispatchEvent.bind(this, a))
      }
    };
  u.boundHandler = u.eventHandler.bind(u);
  var v = {
      shadow: function (a) {
        if (a) return a.shadowRoot || a.webkitShadowRoot
      },
      canTarget: function (a) {
        return a && Boolean(a.elementFromPoint)
      },
      targetingShadow: function (a) {
        var b = this.shadow(a);
        if (this.canTarget(b)) return b
      },
      olderShadow: function (a) {
        var b = a.olderShadowRoot;
        if (!b) {
          var c = a.querySelector("shadow");
          c && (b = c.olderShadowRoot)
        }
        return b
      },
      allShadows: function (a) {
        for (var b = [], c = this.shadow(a); c;) b.push(c), c = this.olderShadow(c);
        return b
      },
      searchRoot: function (a, b, c) {
        if (a) {
          var d, e, f = a.elementFromPoint(b, c);
          for (e = this.targetingShadow(f); e;) {
            if (d = e.elementFromPoint(b, c)) {
              var g = this.targetingShadow(d);
              return this.searchRoot(g, b, c) || d
            }
            e = this.olderShadow(e)
          }
          return f
        }
      },
      owner: function (a) {
        for (var b = a; b.parentNode;) b = b.parentNode;
        return b.nodeType !== Node.DOCUMENT_NODE && b.nodeType !== Node.DOCUMENT_FRAGMENT_NODE && (b = document), b
      },
      findTarget: function (a) {
        var b = a.clientX,
          c = a.clientY,
          d = this.owner(a.target);
        return d.elementFromPoint(b, c) || (d = document), this.searchRoot(d, b, c)
      }
    },
    w = Array.prototype.forEach.call.bind(Array.prototype.forEach),
    x = Array.prototype.map.call.bind(Array.prototype.map),
    y = Array.prototype.slice.call.bind(Array.prototype.slice),
    z = Array.prototype.filter.call.bind(Array.prototype.filter),
    A = window.MutationObserver || window.WebKitMutationObserver,
    B = "[touch-action]",
    C = {
      subtree: !0,
      childList: !0,
      attributes: !0,
      attributeOldValue: !0,
      attributeFilter: ["touch-action"]
    };
  c.prototype = {
    watchSubtree: function (a) {
      //
      this.observer && v.canTarget(a) && this.observer.observe(a, C)
    },
    enableOnSubtree: function (a) {
      this.watchSubtree(a), a === document && "complete" !== document.readyState ? this.installOnLoad() : this.installNewSubtree(a)
    },
    installNewSubtree: function (a) {
      w(this.findElements(a), this.addElement, this)
    },
    findElements: function (a) {
      return a.querySelectorAll ? a.querySelectorAll(B) : []
    },
    removeElement: function (a) {
      this.removeCallback(a)
    },
    addElement: function (a) {
      this.addCallback(a)
    },
    elementChanged: function (a, b) {
      this.changedCallback(a, b)
    },
    concatLists: function (a, b) {
      return a.concat(y(b))
    },
    installOnLoad: function () {
      document.addEventListener("readystatechange", function () {
        "complete" === document.readyState && this.installNewSubtree(document)
      }.bind(this))
    },
    isElement: function (a) {
      return a.nodeType === Node.ELEMENT_NODE
    },
    flattenMutationTree: function (a) {
      var b = x(a, this.findElements, this);
      return b.push(z(a, this.isElement)), b.reduce(this.concatLists, [])
    },
    mutationWatcher: function (a) {
      a.forEach(this.mutationHandler, this)
    },
    mutationHandler: function (a) {
      if ("childList" === a.type) {
        var b = this.flattenMutationTree(a.addedNodes);
        b.forEach(this.addElement, this);
        var c = this.flattenMutationTree(a.removedNodes);
        c.forEach(this.removeElement, this)
      } else "attributes" === a.type && this.elementChanged(a.target, a.oldValue)
    }
  };
  var D = ["none", "auto", "pan-x", "pan-y", {
      rule: "pan-x pan-y",
      selectors: ["pan-x pan-y", "pan-y pan-x"]
    }],
    E = "",
    F = window.PointerEvent || window.MSPointerEvent,
    G = !window.ShadowDOMPolyfill && document.head.createShadowRoot,
    H = u.pointermap,
    I = 25,
    J = [1, 4, 2, 8, 16],
    K = !1;
  try {
    K = 1 === new MouseEvent("test", {
      buttons: 1
    }).buttons
  } catch (L) {}
  var M, N = {
      POINTER_ID: 1,
      POINTER_TYPE: "mouse",
      events: ["mousedown", "mousemove", "mouseup", "mouseover", "mouseout"],
      register: function (a) {
        u.listen(a, this.events)
      },
      unregister: function (a) {
        u.unlisten(a, this.events)
      },
      lastTouches: [],
      isEventSimulatedFromTouch: function (a) {
        for (var b, c = this.lastTouches, d = a.clientX, e = a.clientY, f = 0, g = c.length; f < g && (b = c[f]); f++) {
          var h = Math.abs(d - b.x),
            i = Math.abs(e - b.y);
          if (h <= I && i <= I) return !0
        }
      },
      prepareEvent: function (a) {
        var b = u.cloneEvent(a),
          c = b.preventDefault;
        return b.preventDefault = function () {
          a.preventDefault(), c()
        }, b.pointerId = this.POINTER_ID, b.isPrimary = !0, b.pointerType = this.POINTER_TYPE, b
      },
      prepareButtonsForMove: function (a, b) {
        var c = H.get(this.POINTER_ID);
        0 !== b.which && c ? a.buttons = c.buttons : a.buttons = 0, b.buttons = a.buttons
      },
      mousedown: function (a) {
        if (!this.isEventSimulatedFromTouch(a)) {
          var b = H.get(this.POINTER_ID),
            c = this.prepareEvent(a);
          K || (c.buttons = J[c.button], b && (c.buttons |= b.buttons), a.buttons = c.buttons), H.set(this.POINTER_ID, a), b && 0 !== b.buttons ? u.move(c) : u.down(c)
        }
      },
      mousemove: function (a) {
        if (!this.isEventSimulatedFromTouch(a)) {
          var b = this.prepareEvent(a);
          K || this.prepareButtonsForMove(b, a), b.button = -1, H.set(this.POINTER_ID, a), u.move(b)
        }
      },
      mouseup: function (a) {
        if (!this.isEventSimulatedFromTouch(a)) {
          var b = H.get(this.POINTER_ID),
            c = this.prepareEvent(a);
          if (!K) {
            var d = J[c.button];
            c.buttons = b ? b.buttons & ~d : 0, a.buttons = c.buttons
          }
          H.set(this.POINTER_ID, a),
            c.buttons &= ~J[c.button], 0 === c.buttons ? u.up(c) : u.move(c)
        }
      },
      mouseover: function (a) {
        if (!this.isEventSimulatedFromTouch(a)) {
          var b = this.prepareEvent(a);
          K || this.prepareButtonsForMove(b, a), b.button = -1, H.set(this.POINTER_ID, a), u.enterOver(b)
        }
      },
      mouseout: function (a) {
        if (!this.isEventSimulatedFromTouch(a)) {
          var b = this.prepareEvent(a);
          K || this.prepareButtonsForMove(b, a), b.button = -1, u.leaveOut(b)
        }
      },
      cancel: function (a) {
        var b = this.prepareEvent(a);
        u.cancel(b), this.deactivateMouse()
      },
      deactivateMouse: function () {
        H["delete"](this.POINTER_ID)
      }
    },
    O = u.captureInfo,
    P = v.findTarget.bind(v),
    Q = v.allShadows.bind(v),
    R = u.pointermap,
    S = 2500,
    T = 200,
    U = "touch-action",
    V = {
      events: ["touchstart", "touchmove", "touchend", "touchcancel"],
      register: function (a) {
        M.enableOnSubtree(a)
      },
      unregister: function () {},
      elementAdded: function (a) {
        var b = a.getAttribute(U),
          c = this.touchActionToScrollType(b);
        c && (a._scrollType = c, u.listen(a, this.events),
          Q(a).forEach(function (a) {
            a._scrollType = c, u.listen(a, this.events)
          }, this))
      },
      elementRemoved: function (a) {
        a._scrollType = void 0, u.unlisten(a, this.events),
          Q(a).forEach(function (a) {
            a._scrollType = void 0, u.unlisten(a, this.events)
          }, this)
      },
      elementChanged: function (a, b) {
        var c = a.getAttribute(U),
          d = this.touchActionToScrollType(c),
          e = this.touchActionToScrollType(b);
        d && e ? (a._scrollType = d, Q(a).forEach(function (a) {
          a._scrollType = d
        }, this)) : e ? this.elementRemoved(a) : d && this.elementAdded(a)
      },
      scrollTypes: {
        EMITTER: "none",
        XSCROLLER: "pan-x",
        YSCROLLER: "pan-y",
        SCROLLER: /^(?:pan-x pan-y)|(?:pan-y pan-x)|auto$/
      },
      touchActionToScrollType: function (a) {
        var b = a,
          c = this.scrollTypes;
        return "none" === b ? "none" : b === c.XSCROLLER ? "X" : b === c.YSCROLLER ? "Y" : c.SCROLLER.exec(b) ? "XY" : void 0
      },
      POINTER_TYPE: "touch",
      firstTouch: null,
      isPrimaryTouch: function (a) {
        return this.firstTouch === a.identifier
      },
      setPrimaryTouch: function (a) {
        (0 === R.size || 1 === R.size && R.has(1)) && (this.firstTouch = a.identifier, this.firstXY = {
          X: a.clientX,
          Y: a.clientY
        }, this.scrolling = !1, this.cancelResetClickCount())
      },
      removePrimaryPointer: function (a) {
        a.isPrimary && (this.firstTouch = null, this.firstXY = null, this.resetClickCount())
      },
      clickCount: 0,
      resetId: null,
      resetClickCount: function () {
        var a = function () {
          this.clickCount = 0, this.resetId = null
        }.bind(this);
        this.resetId = setTimeout(a, T)
      },
      cancelResetClickCount: function () {
        this.resetId && clearTimeout(this.resetId)
      },
      typeToButtons: function (a) {
        var b = 0;
        return "touchstart" !== a && "touchmove" !== a || (b = 1), b
      },
      touchToPointer: function (a) {
        var b = this.currentTouchEvent,
          c = u.cloneEvent(a),
          d = c.pointerId = a.identifier + 2;
        c.target = O[d] || P(c), c.bubbles = !0, c.cancelable = !0, c.detail = this.clickCount, c.button = 0, c.buttons = this.typeToButtons(b.type), c.width = 2 * (a.radiusX || a.webkitRadiusX || 0), c.height = 2 * (a.radiusY || a.webkitRadiusY || 0), c.pressure = a.force || a.webkitForce || .5, c.isPrimary = this.isPrimaryTouch(a), c.pointerType = this.POINTER_TYPE,
          c.altKey = b.altKey, c.ctrlKey = b.ctrlKey, c.metaKey = b.metaKey, c.shiftKey = b.shiftKey;
        var e = this;
        return c.preventDefault = function () {
          e.scrolling = !1, e.firstXY = null, b.preventDefault()
        }, c
      },
      processTouches: function (a, b) {
        var c = a.changedTouches;
        this.currentTouchEvent = a;
        for (var d, e = 0; e < c.length; e++) d = c[e], b.call(this, this.touchToPointer(d))
      },
      shouldScroll: function (a) {
        if (this.firstXY) {
          var b, c = a.currentTarget._scrollType;
          if ("none" === c)
            b = !1;
          else if ("XY" === c)
            b = !0;
          else {
            var d = a.changedTouches[0],
              e = c,
              f = "Y" === c ? "X" : "Y",
              g = Math.abs(d["client" + e] - this.firstXY[e]),
              h = Math.abs(d["client" + f] - this.firstXY[f]);
            b = g >= h
          }
          return this.firstXY = null, b
        }
      },
      findTouch: function (a, b) {
        for (var c, d = 0, e = a.length; d < e && (c = a[d]); d++)
          if (c.identifier === b) return !0
      },
      vacuumTouches: function (a) {
        var b = a.touches;
        if (R.size >= b.length) {
          var c = [];
          R.forEach(function (a, d) {
            if (1 !== d && !this.findTouch(b, d - 2)) {
              var e = a.out;
              c.push(e)
            }
          }, this), c.forEach(this.cancelOut, this)
        }
      },
      touchstart: function (a) {
        this.vacuumTouches(a), this.setPrimaryTouch(a.changedTouches[0]), this.dedupSynthMouse(a), this.scrolling || (this.clickCount++, this.processTouches(a, this.overDown))
      },
      overDown: function (a) {
        R.set(a.pointerId, {
          target: a.target,
          out: a,
          outTarget: a.target
        }), u.enterOver(a), u.down(a)
      },
      touchmove: function (a) {
        this.scrolling || (this.shouldScroll(a) ? (this.scrolling = !0, this.touchcancel(a)) : (a.preventDefault(), this.processTouches(a, this.moveOverOut)))
      },
      moveOverOut: function (a) {
        var b = a,
          c = R.get(b.pointerId);
        if (c) {
          var d = c.out,
            e = c.outTarget;
          u.move(b), d && e !== b.target && (d.relatedTarget = b.target, b.relatedTarget = e,
            d.target = e, b.target ? (u.leaveOut(d), u.enterOver(b)) : (
              b.target = e, b.relatedTarget = null, this.cancelOut(b))), c.out = b, c.outTarget = b.target
        }
      },
      touchend: function (a) {
        this.dedupSynthMouse(a), this.processTouches(a, this.upOut)
      },
      upOut: function (a) {
        this.scrolling || (u.up(a), u.leaveOut(a)), this.cleanUpPointer(a)
      },
      touchcancel: function (a) {
        this.processTouches(a, this.cancelOut)
      },
      cancelOut: function (a) {
        u.cancel(a), u.leaveOut(a), this.cleanUpPointer(a)
      },
      cleanUpPointer: function (a) {
        R["delete"](a.pointerId), this.removePrimaryPointer(a)
      },
      dedupSynthMouse: function (a) {
        var b = N.lastTouches,
          c = a.changedTouches[0];
        if (this.isPrimaryTouch(c)) {
          var d = {
            x: c.clientX,
            y: c.clientY
          };
          b.push(d);
          var e = function (a, b) {
            var c = a.indexOf(b);
            c > -1 && a.splice(c, 1)
          }.bind(null, b, d);
          setTimeout(e, S)
        }
      }
    };
  M = new c(V.elementAdded, V.elementRemoved, V.elementChanged, V);
  var W, X, Y, Z = u.pointermap,
    $ = window.MSPointerEvent && "number" == typeof window.MSPointerEvent.MSPOINTER_TYPE_MOUSE,
    _ = {
      events: ["MSPointerDown", "MSPointerMove", "MSPointerUp", "MSPointerOut", "MSPointerOver", "MSPointerCancel", "MSGotPointerCapture", "MSLostPointerCapture"],
      register: function (a) {
        u.listen(a, this.events)
      },
      unregister: function (a) {
        u.unlisten(a, this.events)
      },
      POINTER_TYPES: ["", "unavailable", "touch", "pen", "mouse"],
      prepareEvent: function (a) {
        var b = a;
        return $ && (b = u.cloneEvent(a), b.pointerType = this.POINTER_TYPES[a.pointerType]), b
      },
      cleanup: function (a) {
        Z["delete"](a)
      },
      MSPointerDown: function (a) {
        Z.set(a.pointerId, a);
        var b = this.prepareEvent(a);
        u.down(b)
      },
      MSPointerMove: function (a) {
        var b = this.prepareEvent(a);
        u.move(b)
      },
      MSPointerUp: function (a) {
        var b = this.prepareEvent(a);
        u.up(b), this.cleanup(a.pointerId)
      },
      MSPointerOut: function (a) {
        var b = this.prepareEvent(a);
        u.leaveOut(b)
      },
      MSPointerOver: function (a) {
        var b = this.prepareEvent(a);
        u.enterOver(b)
      },
      MSPointerCancel: function (a) {
        var b = this.prepareEvent(a);
        u.cancel(b), this.cleanup(a.pointerId)
      },
      MSLostPointerCapture: function (a) {
        var b = u.makeEvent("lostpointercapture", a);
        u.dispatchEvent(b)
      },
      MSGotPointerCapture: function (a) {
        var b = u.makeEvent("gotpointercapture", a);
        u.dispatchEvent(b)
      }
    },
    aa = window.navigator;
  aa.msPointerEnabled ? (W = function (a) {
    i(a), j(this), k(a) && (u.setCapture(a, this, !0), this.msSetPointerCapture(a))
  }, X = function (a) {
    i(a), u.releaseCapture(a, !0), this.msReleasePointerCapture(a)
  }) : (W = function (a) {
    i(a), j(this), k(a) && u.setCapture(a, this)
  }, X = function (a) {
    i(a), u.releaseCapture(a)
  }), Y = function (a) {
    return !!u.captureInfo[a]
  }, g(), h(), l();
  var ba = {
    dispatcher: u,
    Installer: c,
    PointerEvent: a,
    PointerMap: p,
    targetFinding: v
  };
  return ba
});
///////////////////////////////////////////////

///////////////////////////////////////////////
var config = {"show_fabrication":false,"redraw_on_drag":true,"highlight_pin1":false,"extra_fields":["BOM_Manufacturer","BOM_Manufacturer Part","BOM_Supplier","BOM_Supplier Part"],"dark_mode":false,"bom_view":"left-right","board_rotation":0,"checkboxes":"Sourced,Placed","show_silkscreen":true,"show_pads":true,"layer_view":"FB"};
///////////////////////////////////////////////

///////////////////////////////////////////////
var pcbdata = {"ibom_version":"v2.3-50-g53ae\n","edges_bbox":{"minx":4060,"miny":3063.5,"maxx":4330,"maxy":3173.5},"edges":[{"type":"polyline","net":"S$27033","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4070,3068.5 4320,3068.5"},{"type":"polyline","net":"S$27031","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4065,3163.5 4065,3073.5"},{"type":"polyline","net":"S$27029","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4320,3168.5 4070,3168.5"},{"type":"polyline","net":"S$27027","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4325,3073.5 4325,3163.5"},{"type":"arc","width":1,"svgpath":"M4070,3068.5 A5,5 0 0 0 4065,3073.5","net":""},{"type":"arc","width":1,"svgpath":"M 4065 3163.5 A 5 5 0 0 0 4070 3168.5","net":""},{"type":"arc","width":1,"svgpath":"M 4325 3073.5 A 5 5 0 0 0 4320 3068.5","net":""},{"type":"arc","width":1,"svgpath":"M 4320 3168.5 A 5 5 0 0 0 4325 3163.5","net":""},{"type":"circle","start":[4080,3083.5],"radius":6.6929,"width":0.5},{"type":"circle","start":[4080,3153.5],"radius":6.6929,"width":0.5},{"type":"circle","start":[4310,3083.5],"radius":6.6929,"width":0.5},{"type":"circle","start":[4310,3153.5],"radius":6.6929,"width":0.5}],"drawings":{"silkscreen":{"F":[{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4221.1185,3119.0374 4221.1185,3119.0374 4221.1185,3119.0241"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4216.6302,3119.0374 4216.9149,3119.0374"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4210.8815,3119.0108 4210.8815,3119.0108 4210.8815,3118.9574"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4215.2913,3119.0108 4215.0851,3119.0108"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.7874,"svgpath":"M4218.008,3117.0315 4221.1185,3117.031 4221.1185,3120.969 4218.0865,3120.969 4218.0475,3120.969"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4216.6302,3116.986 4216.6302,3121.0017"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4215.2913,3116.9921 4215.2913,3121.0078"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.7874,"svgpath":"M4213.9922,3117.0315 4210.8815,3117.031 4210.8815,3120.969 4214.0315,3120.969"},{"type":"text","svgpath":"M 4216.9382 3104.1057 L 4216.3182 3104.3057 L 4215.9082 3104.9257 L 4215.7082 3105.9457 L 4215.7082 3106.5557 L 4215.9082 3107.5857 L 4216.3182 3108.1957 L 4216.9382 3108.3957 L 4217.3482 3108.3957 L 4217.9582 3108.1957 L 4218.3682 3107.5857 L 4218.5682 3106.5557 L 4218.5682 3105.9457 L 4218.3682 3104.9257 L 4217.9582 3104.3057 L 4217.3482 3104.1057 L 4216.9382 3104.1057 M 4220.1282 3107.3757 L 4219.9182 3107.5857 L 4220.1282 3107.7857 L 4220.3282 3107.5857 L 4220.1282 3107.3757 M 4221.6782 3104.9257 L 4222.0882 3104.7157 L 4222.7082 3104.1057 L 4222.7082 3108.3957 M 4224.0582 3105.5357 L 4224.0582 3107.5857 L 4224.2582 3108.1957 L 4224.6682 3108.3957 L 4225.2782 3108.3957 L 4225.6882 3108.1957 L 4226.3082 3107.5857 M 4226.3082 3105.5357 L 4226.3082 3108.3957 M 4227.6582 3104.1057 L 4227.6582 3108.3957 M 4227.6582 3104.1057 L 4230.3082 3104.1057 M 4227.6582 3106.1457 L 4229.2882 3106.1457","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":"","val":1},{"type":"text","svgpath":"M 4208.5432 3118.6607 L 4208.9532 3118.4507 L 4209.3632 3118.0407 L 4209.5632 3117.6407 L 4209.5632 3116.8207 L 4209.3632 3116.4107 L 4208.9532 3116.0007 L 4208.5432 3115.7907 L 4207.9232 3115.5907 L 4206.9032 3115.5907 L 4206.2932 3115.7907 L 4205.8832 3116.0007 L 4205.4732 3116.4107 L 4205.2732 3116.8207 L 4205.2732 3117.6407 L 4205.4732 3118.0407 L 4205.8832 3118.4507 L 4206.2932 3118.6607 M 4209.5632 3120.4207 L 4209.5632 3122.6707 L 4207.9232 3121.4407 L 4207.9232 3122.0507 L 4207.7232 3122.4607 L 4207.5232 3122.6707 L 4206.9032 3122.8707 L 4206.4932 3122.8707 L 4205.8832 3122.6707 L 4205.4732 3122.2607 L 4205.2732 3121.6407 L 4205.2732 3121.0307 L 4205.4732 3120.4207 L 4205.6732 3120.2107 L 4206.0832 3120.0107","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":"","ref":1},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4210.8815,3128.4626 4210.8815,3128.4626 4210.8815,3128.4759"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4215.3698,3128.4626 4215.0851,3128.4626"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4221.1185,3128.4892 4221.1185,3128.4892 4221.1185,3128.5426"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4216.7087,3128.4892 4216.9149,3128.4892"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.7874,"svgpath":"M4213.992,3130.4685 4210.8815,3130.469 4210.8815,3126.531 4213.9135,3126.531 4213.9525,3126.531"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4215.3698,3130.514 4215.3698,3126.4983"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4216.7087,3130.5079 4216.7087,3126.4922"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.7874,"svgpath":"M4218.0078,3130.4685 4221.1185,3130.469 4221.1185,3126.531 4217.9685,3126.531"},{"type":"text","svgpath":"M 4202.9221 3139.1042 L 4202.3021 3139.3042 L 4201.8921 3139.9242 L 4201.6921 3140.9442 L 4201.6921 3141.5542 L 4201.8921 3142.5842 L 4202.3021 3143.1942 L 4202.9221 3143.3942 L 4203.3321 3143.3942 L 4203.9421 3143.1942 L 4204.3521 3142.5842 L 4204.5521 3141.5542 L 4204.5521 3140.9442 L 4204.3521 3139.9242 L 4203.9421 3139.3042 L 4203.3321 3139.1042 L 4202.9221 3139.1042 M 4206.1121 3142.3742 L 4205.9021 3142.5842 L 4206.1121 3142.7842 L 4206.3121 3142.5842 L 4206.1121 3142.3742 M 4207.6621 3139.9242 L 4208.0721 3139.7142 L 4208.6921 3139.1042 L 4208.6921 3143.3942 M 4210.0421 3140.5342 L 4210.0421 3142.5842 L 4210.2421 3143.1942 L 4210.6521 3143.3942 L 4211.2621 3143.3942 L 4211.6721 3143.1942 L 4212.2921 3142.5842 M 4212.2921 3140.5342 L 4212.2921 3143.3942 M 4213.6421 3139.1042 L 4213.6421 3143.3942 M 4213.6421 3139.1042 L 4216.2921 3139.1042 M 4213.6421 3141.1442 L 4215.2721 3141.1442","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":"","val":1},{"type":"text","svgpath":"M 4214.8185 3133.2643 L 4214.6085 3132.8543 L 4214.1985 3132.4443 L 4213.7985 3132.2443 L 4212.9785 3132.2443 L 4212.5685 3132.4443 L 4212.1585 3132.8543 L 4211.9485 3133.2643 L 4211.7485 3133.8843 L 4211.7485 3134.9043 L 4211.9485 3135.5143 L 4212.1585 3135.9243 L 4212.5685 3136.3343 L 4212.9785 3136.5343 L 4213.7985 3136.5343 L 4214.1985 3136.3343 L 4214.6085 3135.9243 L 4214.8185 3135.5143 M 4217.1885 3132.2443 L 4216.5785 3132.4443 L 4216.3685 3132.8543 L 4216.3685 3133.2643 L 4216.5785 3133.6743 L 4216.9885 3133.8843 L 4217.7985 3134.0843 L 4218.4185 3134.2843 L 4218.8285 3134.6943 L 4219.0285 3135.1043 L 4219.0285 3135.7243 L 4218.8285 3136.1343 L 4218.6185 3136.3343 L 4218.0085 3136.5343 L 4217.1885 3136.5343 L 4216.5785 3136.3343 L 4216.3685 3136.1343 L 4216.1685 3135.7243 L 4216.1685 3135.1043 L 4216.3685 3134.6943 L 4216.7785 3134.2843 L 4217.3985 3134.0843 L 4218.2085 3133.8843 L 4218.6185 3133.6743 L 4218.8285 3133.2643 L 4218.8285 3132.8543 L 4218.6185 3132.4443 L 4218.0085 3132.2443 L 4217.1885 3132.2443","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":"","ref":1},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4210.8815,3108.4626 4210.8815,3108.4626 4210.8815,3108.4759"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4215.3698,3108.4626 4215.0851,3108.4626"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4221.1185,3108.4892 4221.1185,3108.4892 4221.1185,3108.5426"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4216.7087,3108.4892 4216.9149,3108.4892"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.7874,"svgpath":"M4213.992,3110.4685 4210.8815,3110.469 4210.8815,3106.531 4213.9135,3106.531 4213.9525,3106.531"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4215.3698,3110.514 4215.3698,3106.4983"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.5,"svgpath":"M4216.7087,3110.5079 4216.7087,3106.4922"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":0.7874,"svgpath":"M4218.0078,3110.4685 4221.1185,3110.469 4221.1185,3106.531 4217.9685,3106.531"},{"type":"text","svgpath":"M 4202.9221 3119.1042 L 4202.3021 3119.3042 L 4201.8921 3119.9242 L 4201.6921 3120.9442 L 4201.6921 3121.5542 L 4201.8921 3122.5842 L 4202.3021 3123.1942 L 4202.9221 3123.3942 L 4203.3321 3123.3942 L 4203.9421 3123.1942 L 4204.3521 3122.5842 L 4204.5521 3121.5542 L 4204.5521 3120.9442 L 4204.3521 3119.9242 L 4203.9421 3119.3042 L 4203.3321 3119.1042 L 4202.9221 3119.1042 M 4206.1121 3122.3742 L 4205.9021 3122.5842 L 4206.1121 3122.7842 L 4206.3121 3122.5842 L 4206.1121 3122.3742 M 4207.6621 3119.9242 L 4208.0721 3119.7142 L 4208.6921 3119.1042 L 4208.6921 3123.3942 M 4210.0421 3120.5342 L 4210.0421 3122.5842 L 4210.2421 3123.1942 L 4210.6521 3123.3942 L 4211.2621 3123.3942 L 4211.6721 3123.1942 L 4212.2921 3122.5842 M 4212.2921 3120.5342 L 4212.2921 3123.3942 M 4213.6421 3119.1042 L 4213.6421 3123.3942 M 4213.6421 3119.1042 L 4216.2921 3119.1042 M 4213.6421 3121.1442 L 4215.2721 3121.1442","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":"","val":1},{"type":"text","svgpath":"M 4212.07 3101.48 L 4211.86 3101.07 L 4211.45 3100.66 L 4211.05 3100.46 L 4210.23 3100.46 L 4209.82 3100.66 L 4209.41 3101.07 L 4209.2 3101.48 L 4209 3102.1 L 4209 3103.12 L 4209.2 3103.73 L 4209.41 3104.14 L 4209.82 3104.55 L 4210.23 3104.75 L 4211.05 3104.75 L 4211.45 3104.55 L 4211.86 3104.14 L 4212.07 3103.73 M 4216.08 3101.89 L 4215.87 3102.5 L 4215.46 3102.91 L 4214.85 3103.12 L 4214.65 3103.12 L 4214.03 3102.91 L 4213.62 3102.5 L 4213.42 3101.89 L 4213.42 3101.69 L 4213.62 3101.07 L 4214.03 3100.66 L 4214.65 3100.46 L 4214.85 3100.46 L 4215.46 3100.66 L 4215.87 3101.07 L 4216.08 3101.89 L 4216.08 3102.91 L 4215.87 3103.94 L 4215.46 3104.55 L 4214.85 3104.75 L 4214.44 3104.75 L 4213.83 3104.55 L 4213.62 3104.14","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":"","ref":1},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4270.9841,3123.5 4270.9841,3113.5"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4299.606,3095.272 4299.606,3141.729 4252.362,3141.729 4252.362,3095.272 4299.606,3095.272"},{"type":"arc","width":1,"svgpath":"M 4270.9841 3123.5 A 7.0711 7.0711 0 1 0 4270.9841 3113.5","net":""},{"type":"circle","_svgpath":"M 4275.984, 3118.5 m -11.811, 0 a 11.811,11.811 0 1,0 23.622,0 a 11.811,11.811 0 1,0 -23.622,0","start":[4275.984,3118.5],"radius":11.811,"width":"1","net":""},{"type":"text","svgpath":"M 4316.573 3129.3198 L 4320.863 3129.3198 M 4316.573 3129.3198 L 4316.573 3126.6598 M 4318.613 3129.3198 L 4318.613 3127.6798 M 4320.863 3129.3198 L 4320.863 3126.6598 M 4317.593 3122.2398 L 4317.183 3122.4498 L 4316.773 3122.8598 L 4316.573 3123.2698 L 4316.573 3124.0798 L 4316.773 3124.4898 L 4317.183 3124.8998 L 4317.593 3125.1098 L 4318.213 3125.3098 L 4319.233 3125.3098 L 4319.843 3125.1098 L 4320.253 3124.8998 L 4320.663 3124.4898 L 4320.863 3124.0798 L 4320.863 3123.2698 L 4320.663 3122.8598 L 4320.253 3122.4498 L 4319.843 3122.2398 M 4317.393 3120.8898 L 4317.183 3120.4798 L 4316.573 3119.8698 L 4320.863 3119.8698 M 4317.393 3118.5198 L 4317.183 3118.1098 L 4316.573 3117.4998 L 4320.863 3117.4998","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":"","val":1},{"type":"text","svgpath":"M 4313.253 3120.36 L 4313.663 3119.95 L 4313.863 3119.34 L 4313.863 3118.52 L 4313.663 3117.91 L 4313.253 3117.5 L 4312.843 3117.5 L 4312.433 3117.7 L 4312.223 3117.91 L 4312.023 3118.32 L 4311.613 3119.55 L 4311.413 3119.95 L 4311.203 3120.16 L 4310.793 3120.36 L 4310.183 3120.36 L 4309.773 3119.95 L 4309.573 3119.34 L 4309.573 3118.52 L 4309.773 3117.91 L 4310.183 3117.5 M 4313.863 3121.71 L 4309.573 3122.74 M 4313.863 3123.76 L 4309.573 3122.74 M 4313.863 3123.76 L 4309.573 3124.78 M 4313.863 3125.8 L 4309.573 3124.78 M 4313.043 3127.15 L 4313.253 3127.56 L 4313.863 3128.18 L 4309.573 3128.18","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":"","ref":1},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4089,3095.5 4238.606,3095.5 4238.606,3142.744 4089,3142.744 4089,3095.5"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4108.685,3096.484 4226.795,3096.484 4226.795,3141.76 4108.685,3141.76 4108.685,3096.484"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4116.953,3105.067 4205.063,3105.067 4205.063,3127.036 4116.953,3127.036 4116.953,3105.067"},{"type":"text","svgpath":"M 4164.23 3082.96 L 4163.61 3083.16 L 4163.2 3083.78 L 4163 3084.8 L 4163 3085.41 L 4163.2 3086.44 L 4163.61 3087.05 L 4164.23 3087.25 L 4164.64 3087.25 L 4165.25 3087.05 L 4165.66 3086.44 L 4165.86 3085.41 L 4165.86 3084.8 L 4165.66 3083.78 L 4165.25 3083.16 L 4164.64 3082.96 L 4164.23 3082.96 M 4167.42 3086.23 L 4167.21 3086.44 L 4167.42 3086.64 L 4167.62 3086.44 L 4167.42 3086.23 M 4171.63 3084.39 L 4171.43 3085 L 4171.02 3085.41 L 4170.4 3085.62 L 4170.2 3085.62 L 4169.59 3085.41 L 4169.18 3085 L 4168.97 3084.39 L 4168.97 3084.19 L 4169.18 3083.57 L 4169.59 3083.16 L 4170.2 3082.96 L 4170.4 3082.96 L 4171.02 3083.16 L 4171.43 3083.57 L 4171.63 3084.39 L 4171.63 3085.41 L 4171.43 3086.44 L 4171.02 3087.05 L 4170.4 3087.25 L 4170 3087.25 L 4169.38 3087.05 L 4169.18 3086.64 M 4172.98 3083.78 L 4173.39 3083.57 L 4174 3082.96 L 4174 3087.25 M 4176.58 3082.96 L 4176.17 3083.16 L 4175.76 3083.57 L 4175.56 3083.98 L 4175.35 3084.6 L 4175.35 3085.62 L 4175.56 3086.23 L 4175.76 3086.64 L 4176.17 3087.05 L 4176.58 3087.25 L 4177.4 3087.25 L 4177.81 3087.05 L 4178.22 3086.64 L 4178.42 3086.23 L 4178.63 3085.62 L 4178.63 3084.6 L 4178.42 3083.98 L 4178.22 3083.57 L 4177.81 3083.16 L 4177.4 3082.96 L 4176.58 3082.96 M 4179.98 3082.96 L 4179.98 3087.25 M 4179.98 3087.25 L 4182.43 3087.25 M 4183.78 3082.96 L 4183.78 3087.25 M 4183.78 3082.96 L 4186.44 3082.96 M 4183.78 3085 L 4185.42 3085 M 4183.78 3087.25 L 4186.44 3087.25 M 4187.79 3082.96 L 4187.79 3087.25 M 4187.79 3082.96 L 4189.22 3082.96 L 4189.84 3083.16 L 4190.25 3083.57 L 4190.45 3083.98 L 4190.65 3084.6 L 4190.65 3085.62 L 4190.45 3086.23 L 4190.25 3086.64 L 4189.84 3087.05 L 4189.22 3087.25 L 4187.79 3087.25 M 4192 3085.41 L 4195.69 3085.41 M 4197.04 3082.96 L 4197.04 3087.25 M 4198.39 3082.96 L 4198.39 3087.25 M 4202.8 3083.98 L 4202.6 3083.57 L 4202.19 3083.16 L 4201.78 3082.96 L 4200.96 3082.96 L 4200.55 3083.16 L 4200.15 3083.57 L 4199.94 3083.98 L 4199.74 3084.6 L 4199.74 3085.62 L 4199.94 3086.23 L 4200.15 3086.64 L 4200.55 3087.05 L 4200.96 3087.25 L 4201.78 3087.25 L 4202.19 3087.05 L 4202.6 3086.64 L 4202.8 3086.23 M 4204.15 3085.41 L 4207.84 3085.41 M 4209.19 3082.96 L 4209.19 3087.25 M 4211.76 3082.96 L 4211.35 3083.16 L 4210.95 3083.57 L 4210.74 3083.98 L 4210.54 3084.6 L 4210.54 3085.62 L 4210.74 3086.23 L 4210.95 3086.64 L 4211.35 3087.05 L 4211.76 3087.25 L 4212.58 3087.25 L 4212.99 3087.05 L 4213.4 3086.64 L 4213.6 3086.23 L 4213.81 3085.62 L 4213.81 3084.6 L 4213.6 3083.98 L 4213.4 3083.57 L 4212.99 3083.16 L 4212.58 3082.96 L 4211.76 3082.96 M 4217.2 3082.96 L 4215.16 3085.82 L 4218.23 3085.82 M 4217.2 3082.96 L 4217.2 3087.25","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":"","val":1},{"type":"text","svgpath":"M 4163 3089.96 L 4163 3093.03 L 4163.2 3093.64 L 4163.61 3094.05 L 4164.23 3094.25 L 4164.64 3094.25 L 4165.25 3094.05 L 4165.66 3093.64 L 4165.86 3093.03 L 4165.86 3089.96 M 4169.67 3090.57 L 4169.46 3090.16 L 4168.85 3089.96 L 4168.44 3089.96 L 4167.83 3090.16 L 4167.42 3090.78 L 4167.21 3091.8 L 4167.21 3092.82 L 4167.42 3093.64 L 4167.83 3094.05 L 4168.44 3094.25 L 4168.65 3094.25 L 4169.26 3094.05 L 4169.67 3093.64 L 4169.87 3093.03 L 4169.87 3092.82 L 4169.67 3092.21 L 4169.26 3091.8 L 4168.65 3091.6 L 4168.44 3091.6 L 4167.83 3091.8 L 4167.42 3092.21 L 4167.21 3092.82","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":"","ref":1},{"type":"text","svgpath":"M 4102.25 3105.5 L 4101.96 3105.78 L 4101.82 3106.21 L 4101.82 3106.78 L 4101.96 3107.21 L 4102.25 3107.5 L 4102.54 3107.5 L 4102.82 3107.36 L 4102.97 3107.21 L 4103.11 3106.93 L 4103.4 3106.07 L 4103.54 3105.78 L 4103.68 3105.64 L 4103.97 3105.5 L 4104.4 3105.5 L 4104.69 3105.78 L 4104.83 3106.21 L 4104.83 3106.78 L 4104.69 3107.21 L 4104.4 3107.5 M 4101.82 3104.55 L 4104.83 3104.55 M 4101.82 3104.55 L 4101.82 3103.55 L 4101.96 3103.12 L 4102.25 3102.83 L 4102.54 3102.69 L 4102.97 3102.55 L 4103.68 3102.55 L 4104.11 3102.69 L 4104.4 3102.83 L 4104.69 3103.12 L 4104.83 3103.55 L 4104.83 3104.55 M 4101.82 3100.46 L 4104.83 3101.6 M 4101.82 3100.46 L 4104.83 3099.31 M 4103.83 3101.17 L 4103.83 3099.74","useTrueTypeFontRendering":false,"thickness":0.5984,"width":0.5984,"net":""},{"type":"text","svgpath":"M 4102.25 3115.5 L 4101.96 3115.78 L 4101.82 3116.21 L 4101.82 3116.78 L 4101.96 3117.21 L 4102.25 3117.5 L 4102.54 3117.5 L 4102.82 3117.36 L 4102.97 3117.21 L 4103.11 3116.93 L 4103.4 3116.07 L 4103.54 3115.78 L 4103.68 3115.64 L 4103.97 3115.5 L 4104.4 3115.5 L 4104.69 3115.78 L 4104.83 3116.21 L 4104.83 3116.78 L 4104.69 3117.21 L 4104.4 3117.5 M 4102.54 3112.4 L 4102.25 3112.55 L 4101.96 3112.83 L 4101.82 3113.12 L 4101.82 3113.69 L 4101.96 3113.98 L 4102.25 3114.26 L 4102.54 3114.41 L 4102.97 3114.55 L 4103.68 3114.55 L 4104.11 3114.41 L 4104.4 3114.26 L 4104.69 3113.98 L 4104.83 3113.69 L 4104.83 3113.12 L 4104.69 3112.83 L 4104.4 3112.55 L 4104.11 3112.4 M 4101.82 3111.46 L 4104.83 3111.46 M 4104.83 3111.46 L 4104.83 3109.74","useTrueTypeFontRendering":false,"thickness":0.5984,"width":0.5984,"net":""},{"type":"text","svgpath":"M 4101.82 3128.5 L 4104.83 3127.35 M 4101.82 3126.21 L 4104.83 3127.35 M 4102.54 3123.12 L 4102.25 3123.26 L 4101.96 3123.55 L 4101.82 3123.83 L 4101.82 3124.41 L 4101.96 3124.69 L 4102.25 3124.98 L 4102.54 3125.12 L 4102.97 3125.26 L 4103.68 3125.26 L 4104.11 3125.12 L 4104.4 3124.98 L 4104.69 3124.69 L 4104.83 3124.41 L 4104.83 3123.83 L 4104.69 3123.55 L 4104.4 3123.26 L 4104.11 3123.12 M 4102.54 3120.02 L 4102.25 3120.17 L 4101.96 3120.45 L 4101.82 3120.74 L 4101.82 3121.31 L 4101.96 3121.6 L 4102.25 3121.89 L 4102.54 3122.03 L 4102.97 3122.17 L 4103.68 3122.17 L 4104.11 3122.03 L 4104.4 3121.89 L 4104.69 3121.6 L 4104.83 3121.31 L 4104.83 3120.74 L 4104.69 3120.45 L 4104.4 3120.17 L 4104.11 3120.02","useTrueTypeFontRendering":false,"thickness":0.5984,"width":0.5984,"net":""},{"type":"text","svgpath":"M 4102.54 3136.35 L 4102.25 3136.5 L 4101.96 3136.78 L 4101.82 3137.07 L 4101.82 3137.64 L 4101.96 3137.93 L 4102.25 3138.21 L 4102.54 3138.36 L 4102.97 3138.5 L 4103.68 3138.5 L 4104.11 3138.36 L 4104.4 3138.21 L 4104.69 3137.93 L 4104.83 3137.64 L 4104.83 3137.07 L 4104.69 3136.78 L 4104.4 3136.5 L 4104.11 3136.35 L 4103.68 3136.35 M 4103.68 3137.07 L 4103.68 3136.35 M 4101.82 3135.41 L 4104.83 3135.41 M 4101.82 3135.41 L 4104.83 3133.4 M 4101.82 3133.4 L 4104.83 3133.4 M 4101.82 3132.46 L 4104.83 3132.46 M 4101.82 3132.46 L 4101.82 3131.46 L 4101.96 3131.03 L 4102.25 3130.74 L 4102.54 3130.6 L 4102.97 3130.45 L 4103.68 3130.45 L 4104.11 3130.6 L 4104.4 3130.74 L 4104.69 3131.03 L 4104.83 3131.46 L 4104.83 3132.46","useTrueTypeFontRendering":false,"thickness":0.5984,"width":0.5984,"net":""},{"type":"circle","_svgpath":"M 4080, 3083.5 m -7.874, 0 a 7.874,7.874 0 1,0 15.748,0 a 7.874,7.874 0 1,0 -15.748,0","start":[4080,3083.5],"radius":7.874,"width":"7.874","net":""},{"type":"circle","_svgpath":"M 4080, 3153.5 m -7.874, 0 a 7.874,7.874 0 1,0 15.748,0 a 7.874,7.874 0 1,0 -15.748,0","start":[4080,3153.5],"radius":7.874,"width":"7.874","net":""},{"type":"circle","_svgpath":"M 4310, 3083.5 m -7.874, 0 a 7.874,7.874 0 1,0 15.748,0 a 7.874,7.874 0 1,0 -15.748,0","start":[4310,3083.5],"radius":7.874,"width":"7.874","net":""},{"type":"circle","_svgpath":"M 4310, 3153.5 m -7.874, 0 a 7.874,7.874 0 1,0 15.748,0 a 7.874,7.874 0 1,0 -15.748,0","start":[4310,3153.5],"radius":7.874,"width":"7.874","net":""},{"type":"polygon","svgpath":"M 4143.7264 3145.3623 C 4143.627 3145.7176 4143.6374 3153.2562 4143.7378 3153.6562 L 4143.8108 3153.947 L 4144.6139 3153.8834 C 4146.2359 3153.755 4146.5109 3153.7096 4146.5109 3153.5701 C 4146.5109 3153.379 4146.1701 3153.3081 4145.2433 3153.3064 C 4144.804 3153.3056 4144.3704 3153.2766 4144.2798 3153.2418 C 4144.1335 3153.1856 4144.115 3152.7254 4144.115 3149.1272 C 4144.115 3145.6186 4144.0944 3145.0758 4143.9608 3145.0758 C 4143.8759 3145.0758 4143.7704 3145.2047 4143.7264 3145.3623 M 4129.74 3145.3272 C 4129.3941 3145.4517 4129.3715 3145.49 4129.299 3146.0744 C 4129.257 3146.4132 4129.2309 3148.3244 4129.2409 3150.3216 L 4129.2592 3153.9527 L 4129.4929 3154.0592 C 4129.654 3154.1326 4129.9725 3154.1291 4130.5188 3154.0478 C 4130.9545 3153.983 4131.5083 3153.9294 4131.7495 3153.9286 C 4132.3248 3153.9267 4132.6567 3153.8325 4132.6567 3153.6711 C 4132.6567 3153.5046 4132.092 3153.4118 4131.0705 3153.4103 C 4129.911 3153.4087 4129.9143 3153.4157 4129.8459 3150.7601 C 4129.7756 3148.0271 4129.8529 3145.9621 4130.0324 3145.7839 C 4130.1231 3145.6938 4130.488 3145.6467 4131.1261 3145.6426 C 4131.6528 3145.6392 4132.1424 3145.6275 4132.214 3145.6166 C 4132.4 3145.5881 4132.3751 3145.3183 4132.1794 3145.2432 C 4131.8867 3145.1309 4130.1158 3145.1918 4129.74 3145.3272 M 4133.9236 3147.0066 L 4133.6802 3147.1837 L 4133.723 3149.2808 C 4133.7697 3151.5733 4133.9001 3152.2458 4134.2842 3152.1755 C 4134.3917 3152.1558 4134.9015 3152.1323 4135.4171 3152.1234 L 4136.3546 3152.1071 L 4136.4187 3150.5446 C 4136.4539 3149.6852 4136.5008 3148.5841 4136.5228 3148.0978 L 4136.5629 3147.2135 L 4136.1463 3147.0733 C 4135.9171 3146.9962 4135.378 3146.9097 4134.9483 3146.8812 C 4134.3198 3146.8395 4134.1195 3146.864 4133.9236 3147.0066 M 4138.7414 3146.9889 C 4138.6582 3147.2058 4138.7394 3151.7146 4138.8282 3151.8031 C 4138.8709 3151.8457 4139.2459 3151.912 4139.6615 3151.9504 C 4140.0771 3151.9887 4140.464 3152.0354 4140.5213 3152.0541 C 4140.5786 3152.0728 4140.7038 3152.0536 4140.7996 3152.0114 C 4140.8954 3151.9693 4141.0683 3151.9854 4141.1839 3152.0473 C 4141.3405 3152.1311 4141.4156 3152.1265 4141.4785 3152.0292 C 4141.5249 3151.9575 4141.578 3150.8723 4141.5964 3149.6178 C 4141.6328 3147.1365 4141.6392 3147.1648 4141.0421 3147.1596 C 4140.8702 3147.1581 4140.4995 3147.0871 4140.2183 3147.0018 C 4139.5671 3146.8043 4138.8148 3146.7977 4138.7414 3146.9889 M 4139.3234 3147.2633 C 4139.3234 3147.3206 4139.2765 3147.3675 4139.2192 3147.3675 C 4139.1619 3147.3675 4139.115 3147.3206 4139.115 3147.2633 C 4139.115 3147.206 4139.1619 3147.1592 4139.2192 3147.1592 C 4139.2765 3147.1592 4139.3234 3147.206 4139.3234 3147.2633 M 4134.5317 3147.3027 C 4134.5317 3147.3243 4134.4497 3147.4063 4134.3494 3147.485 C 4134.1842 3147.6145 4134.1805 3147.6108 4134.3101 3147.4456 C 4134.4461 3147.2721 4134.5317 3147.2169 4134.5317 3147.3027 M 4135.8194 3147.5238 C 4135.7521 3147.6989 4135.5734 3147.7368 4135.5734 3147.5758 C 4135.5734 3147.4026 4135.2786 3147.459 4135.165 3147.654 C 4135.1066 3147.7542 4135.0574 3147.787 4135.0557 3147.7269 C 4135.05 3147.5322 4135.2954 3147.3675 4135.5909 3147.3675 C 4135.8045 3147.3675 4135.8638 3147.4081 4135.8194 3147.5238 M 4140.0652 3147.6461 C 4139.9744 3147.8023 4139.9541 3147.8068 4139.9515 3147.6713 C 4139.9482 3147.4959 4140.0577 3147.3379 4140.1315 3147.4118 C 4140.1559 3147.4361 4140.126 3147.5416 4140.0652 3147.6461 M 4140.9128 3147.6492 C 4140.7844 3147.674 4140.6086 3147.7952 4140.5222 3147.9186 C 4140.4357 3148.0421 4140.365 3148.1011 4140.365 3148.0499 C 4140.365 3147.8627 4140.7157 3147.5762 4140.928 3147.59 C 4141.1331 3147.6034 4141.1322 3147.6069 4140.9128 3147.6492 M 4154.1194 3148.1926 C 4153.9796 3148.454 4153.7989 3149.7369 4153.8743 3149.9334 C 4153.9066 3150.0174 4154.009 3150.0715 4154.1021 3150.0537 C 4154.2267 3150.0299 4154.2882 3149.8569 4154.3354 3149.3976 C 4154.3707 3149.0545 4154.4345 3148.598 4154.4772 3148.3831 C 4154.5406 3148.0641 4154.5248 3147.9925 4154.3907 3147.9925 C 4154.3004 3147.9925 4154.1783 3148.0825 4154.1194 3148.1926 M 4134.2903 3148.4287 C 4134.2571 3148.5118 4134.2324 3148.4871 4134.2274 3148.3658 C 4134.2229 3148.256 4134.2475 3148.1944 4134.2821 3148.229 C 4134.3167 3148.2637 4134.3204 3148.3535 4134.2903 3148.4287 M 4135.9577 3148.6956 C 4135.9315 3148.7959 4135.91 3148.7139 4135.91 3148.5133 C 4135.91 3148.3128 4135.9315 3148.2308 4135.9577 3148.331 C 4135.9839 3148.4313 4135.9839 3148.5954 4135.9577 3148.6956 M 4140.0816 3148.6216 C 4140.0511 3148.7385 4140.0028 3148.8108 4139.9743 3148.7824 C 4139.918 3148.726 4140.0175 3148.4092 4140.0916 3148.4092 C 4140.1167 3148.4092 4140.1122 3148.5048 4140.0816 3148.6216 M 4121.1279 3148.7477 C 4121.0824 3148.8193 4121.0277 3149.4053 4121.0064 3150.0498 C 4120.9724 3151.0731 4120.9888 3151.2217 4121.135 3151.2217 C 4121.2271 3151.2217 4121.3029 3151.1396 4121.3034 3151.0394 C 4121.3048 3150.7261 4121.5134 3148.9913 4121.5727 3148.7998 C 4121.6134 3148.668 4121.5711 3148.6175 4121.4198 3148.6175 C 4121.3048 3148.6175 4121.1734 3148.6761 4121.1279 3148.7477 M 4134.5317 3148.9759 C 4134.5317 3149.0012 4134.4848 3149.0508 4134.4275 3149.0863 C 4134.3702 3149.1217 4134.3233 3149.101 4134.3233 3149.0403 C 4134.3233 3148.9796 4134.3702 3148.93 4134.4275 3148.93 C 4134.4848 3148.93 4134.5317 3148.9507 4134.5317 3148.9759 M 4155.6254 3149.4702 C 4155.2571 3149.6773 4154.7361 3150.2179 4154.3822 3150.7602 C 4154.1926 3151.0506 4153.886 3151.4608 4153.7009 3151.6716 C 4153.3213 3152.104 4153.0184 3152.1539 4152.2247 3151.915 C 4151.9585 3151.8349 4151.6668 3151.8094 4151.5427 3151.8553 C 4151.4234 3151.8994 4151.0621 3152.3359 4150.7398 3152.8253 C 4150.4175 3153.3147 4149.5685 3154.3451 4148.8532 3155.1152 C 4148.1378 3155.8852 4147.5525 3156.5664 4147.5525 3156.6289 C 4147.5525 3156.8542 4147.8755 3156.7354 4148.2054 3156.3887 C 4148.3906 3156.1941 4149.0243 3155.5168 4149.6136 3154.8836 C 4150.5739 3153.8518 4150.9361 3153.4311 4151.5947 3152.5825 C 4151.7856 3152.3366 4151.8026 3152.3338 4152.1461 3152.4928 C 4153.1081 3152.9381 4153.2064 3152.8927 4154.3159 3151.4915 C 4154.7747 3150.912 4155.3626 3150.2604 4155.6222 3150.0434 C 4156.2451 3149.5227 4156.2474 3149.1204 4155.6254 3149.4702 M 4134.5244 3150.252 C 4134.5284 3150.3775 4134.4848 3150.5092 4134.4275 3150.5446 C 4134.3632 3150.5843 4134.3262 3150.4171 4134.3307 3150.108 C 4134.3362 3149.7323 4134.3604 3149.6592 4134.4275 3149.8154 C 4134.4768 3149.93 4134.5203 3150.1265 4134.5244 3150.252 M 4139.2383 3150.4109 C 4139.1635 3150.4857 4139.115 3150.4918 4139.115 3150.4265 C 4139.115 3150.2875 4139.2382 3150.1643 4139.3077 3150.2338 C 4139.3373 3150.2634 4139.3061 3150.3431 4139.2383 3150.4109 M 4156.9561 3150.86 C 4156.0406 3151.1483 4154.9792 3151.9508 4155.5134 3151.9508 C 4155.728 3151.9508 4157.7609 3150.9043 4157.7609 3150.7938 C 4157.7609 3150.6696 4157.4901 3150.6919 4156.9561 3150.86 M 4118.9067 3150.945 C 4118.9067 3151.0221 4119.1293 3151.3464 4119.4015 3151.6657 C 4119.6736 3151.9851 4120.0251 3152.4494 4120.1827 3152.6975 C 4120.3402 3152.9457 4120.7465 3153.5238 4121.0855 3153.9821 C 4121.5707 3154.6381 4121.7037 3154.8992 4121.7105 3155.2093 C 4121.7231 3155.7813 4121.9288 3155.787 4122.6072 3155.2345 C 4122.9328 3154.9693 4123.2761 3154.7671 4123.37 3154.7851 C 4123.464 3154.8032 4123.799 3155.2001 4124.1144 3155.6672 C 4124.8141 3156.7031 4125.3732 3157.3663 4125.5473 3157.367 C 4125.7661 3157.3679 4125.6946 3157.1277 4125.3144 3156.5843 C 4125.1147 3156.2989 4124.6577 3155.6336 4124.2988 3155.1057 C 4123.9399 3154.5779 4123.5933 3154.1245 4123.5287 3154.0982 C 4123.464 3154.0719 4123.168 3154.2141 4122.871 3154.4141 C 4122.2324 3154.8441 4122.2446 3154.8499 4121.5462 3153.7889 C 4121.2768 3153.3795 4120.6394 3152.5407 4120.13 3151.9248 C 4119.2731 3150.889 4118.9067 3150.5955 4118.9067 3150.945 M 4140.365 3151.1696 C 4140.4724 3151.299 4140.4612 3151.326 4140.2997 3151.327 C 4140.1924 3151.3276 4139.9288 3151.3572 4139.714 3151.3927 C 4139.4015 3151.4443 4139.3234 3151.4246 4139.3234 3151.2943 C 4139.3234 3151.1457 4139.5059 3151.0805 4140.0658 3151.0289 C 4140.1591 3151.0204 4140.2937 3151.0837 4140.365 3151.1696 M 4135.8859 3151.4341 C 4135.8859 3151.5456 4135.0837 3151.6501 4134.791 3151.5767 C 4134.6492 3151.5411 4134.5542 3151.4779 4134.5799 3151.4363 C 4134.6401 3151.3388 4135.8859 3151.3367 4135.8859 3151.4341 M 4116.0942 3152.5263 C 4116.0942 3152.7335 4116.4626 3152.8685 4117.5786 3153.0705 C 4119.0074 3153.329 4118.9851 3153.0383 4117.5441 3152.6194 C 4116.53 3152.3245 4116.0942 3152.2966 4116.0942 3152.5263 M 4134.2793 3157.9067 C 4134.2554 3157.9825 4134.2057 3159.2838 4134.1689 3160.7984 C 4134.1321 3162.3129 4134.0754 3163.6856 4134.0427 3163.8487 L 4133.9834 3164.1453 L 4132.9294 3164.1158 L 4131.8754 3164.0863 L 4131.8989 3162.8363 C 4131.9594 3159.6209 4131.9576 3159.053 4131.8857 3158.5854 C 4131.8179 3158.1442 4131.6049 3157.8637 4131.453 3158.0156 C 4131.384 3158.0847 4131.3135 3163.9224 4131.3777 3164.2631 L 4131.4305 3164.544 L 4132.8509 3164.5756 C 4133.6321 3164.5929 4134.3227 3164.5721 4134.3856 3164.5294 C 4134.5143 3164.4419 4134.6832 3161.472 4134.6861 3159.2441 C 4134.6877 3157.9874 4134.6687 3157.8357 4134.5053 3157.8041 C 4134.4049 3157.7847 4134.3032 3157.8308 4134.2793 3157.9067 M 4146.7872 3157.9024 C 4146.3377 3157.9551 4145.8174 3158.0618 4145.6312 3158.1396 C 4145.2935 3158.2808 4145.2924 3158.2836 4145.2276 3159.2045 C 4145.1919 3159.7124 4145.1315 3160.9723 4145.0933 3162.0044 C 4145.032 3163.6633 4145.0436 3163.8971 4145.1932 3164.0212 C 4145.5416 3164.3104 4145.6769 3164.0936 4145.6867 3163.2302 C 4145.6917 3162.7844 4145.7268 3162.1852 4145.7648 3161.8988 L 4145.8338 3161.3779 L 4146.2504 3161.4095 C 4146.4796 3161.4268 4147.1792 3161.3921 4147.8052 3161.3323 C 4148.4311 3161.2724 4148.9605 3161.2408 4148.9816 3161.2618 C 4149.0027 3161.2829 4149.1769 3161.7453 4149.3688 3162.2892 C 4149.5607 3162.8332 4149.7988 3163.4021 4149.8979 3163.5533 C 4150.0506 3163.7864 4150.9016 3164.4508 4151.0473 3164.4508 C 4151.2103 3164.4508 4151.0457 3163.8808 4150.8001 3163.5951 C 4150.4395 3163.1754 4149.7917 3162.0962 4149.6881 3161.7425 C 4149.6462 3161.5993 4149.3891 3160.8962 4149.1169 3160.18 C 4148.8447 3159.4639 4148.555 3158.6436 4148.4733 3158.3571 C 4148.3333 3157.8665 4148.3038 3157.8354 4147.9646 3157.8215 C 4147.7666 3157.8134 4147.2368 3157.8498 4146.7872 3157.9024 M 4126.1576 3158.4113 C 4126.0654 3158.6416 4125.901 3159.1455 4125.7922 3159.5311 C 4125.3763 3161.0047 4125.1774 3161.6164 4124.819 3162.5238 C 4124.5069 3163.3141 4124.4497 3163.5839 4124.4548 3164.2425 L 4124.4609 3165.0238 L 4126.7099 3164.9933 C 4127.9468 3164.9765 4129.0148 3164.9438 4129.0834 3164.9206 C 4129.1753 3164.8894 4129.2187 3164.036 4129.2488 3161.6698 C 4129.2712 3159.9051 4129.3089 3158.3675 4129.3325 3158.2529 C 4129.3807 3158.0191 4129.1952 3158.008 4127.6447 3158.1525 C 4127.0971 3158.2035 4126.8291 3158.1902 4126.7792 3158.1095 C 4126.6196 3157.8512 4126.3243 3157.9946 4126.1576 3158.4113 M 4138.8207 3158.1268 C 4138.6225 3158.3657 4138.3839 3164.3734 4138.5681 3164.4865 C 4138.6111 3164.5129 4139.0447 3164.4926 4139.5317 3164.4413 C 4140.0187 3164.39 4140.7831 3164.3416 4141.2303 3164.3338 C 4141.786 3164.3241 4142.0293 3164.2824 4141.9985 3164.2022 C 4141.9737 3164.1376 4141.8921 3163.5826 4141.8171 3162.9688 C 4141.7037 3162.0411 4141.7042 3161.809 4141.8198 3161.5929 C 4141.9105 3161.4234 4141.9246 3161.2864 4141.8603 3161.1992 C 4141.7589 3161.0617 4141.8496 3159.006 4141.979 3158.5078 C 4142.0361 3158.2882 4142.0004 3158.22 4141.7746 3158.1171 C 4141.3859 3157.94 4138.9692 3157.948 4138.8207 3158.1268 M 4141.2798 3158.4971 C 4141.3795 3158.5603 4141.4059 3158.9106 4141.384 3159.8757 L 4141.3546 3161.1696 L 4140.6254 3161.2023 C 4140.2244 3161.2202 4139.692 3161.2049 4139.4423 3161.1682 L 4138.9884 3161.1014 L 4139.0298 3159.9897 C 4139.0875 3158.44 4139.1114 3158.4088 4140.2385 3158.4108 C 4140.7378 3158.4117 4141.2064 3158.4505 4141.2798 3158.4971 M 4148.0584 3158.5915 C 4148.2761 3159.0028 4148.8194 3160.7187 4148.7529 3160.7853 C 4148.7135 3160.8248 4148.035 3160.8732 4147.2452 3160.8928 L 4145.8091 3160.9285 L 4145.7571 3160.3199 C 4145.7285 3159.9851 4145.7286 3159.4442 4145.7574 3159.1177 C 4145.818 3158.4295 4145.7875 3158.4452 4147.1062 3158.4234 C 4147.824 3158.4115 4147.9774 3158.4385 4148.0584 3158.5915 M 4128.7344 3159.3727 C 4128.82 3160.4725 4128.8204 3163.1933 4128.735 3163.904 L 4128.6693 3164.4508 L 4127.9608 3164.4508 C 4127.5711 3164.4508 4127.2253 3164.4946 4127.1922 3164.5481 C 4127.1289 3164.6505 4125.2991 3164.5765 4125.09 3164.4631 C 4125.0055 3164.4173 4125.0578 3164.0681 4125.2711 3163.2529 C 4125.4361 3162.6227 4125.617 3161.9151 4125.6732 3161.6803 C 4125.7294 3161.4456 4125.8706 3161.0316 4125.9869 3160.7602 C 4126.1032 3160.4889 4126.1984 3160.1888 4126.1984 3160.0933 C 4126.1985 3159.9977 4126.3362 3159.6286 4126.5045 3159.2729 L 4126.8104 3158.6261 L 4127.6763 3158.5909 C 4128.1525 3158.5716 4128.5703 3158.5462 4128.6048 3158.5345 C 4128.6393 3158.5229 4128.6976 3158.9001 4128.7344 3159.3727 M 4141.3398 3162.3828 C 4141.3766 3162.7349 4141.4067 3163.1973 4141.4067 3163.4102 L 4141.4067 3163.7973 L 4140.7556 3163.8604 C 4140.3976 3163.8951 4139.8217 3163.9539 4139.4758 3163.9913 L 4138.8471 3164.0591 L 4138.9255 3163.0005 C 4138.9687 3162.4184 4139.0318 3161.8971 4139.0657 3161.8423 C 4139.0996 3161.7874 4139.6101 3161.7425 4140.2001 3161.7425 L 4141.2728 3161.7425 L 4141.3398 3162.3828"},{"type":"text","svgpath":"M 4167.18 3153.93L4166.45 3154.29 L4165.73 3155.02 L4165.36 3155.75 L4165 3156.84 L4165 3158.65 L4165.36 3159.75 L4165.73 3160.47 L4166.45 3161.2 L4167.18 3161.56 L4168.64 3161.56 L4169.36 3161.2 L4170.09 3160.47 L4170.45 3159.75 L4170.82 3158.65 L4170.82 3156.84 L4170.45 3155.75 L4170.09 3155.02 L4169.36 3154.29 L4168.64 3153.93 L4167.18 3153.93 M 4173.22 3156.47L4173.22 3160.11 L4173.58 3161.2 L4174.31 3161.56 L4175.4 3161.56 L4176.13 3161.2 L4177.22 3160.11 M 4177.22 3156.47L4177.22 3161.56 M 4179.62 3153.93L4179.62 3161.56 M 4179.62 3157.56L4180.35 3156.84 L4181.07 3156.47 L4182.16 3156.47 L4182.89 3156.84 L4183.62 3157.56 L4183.98 3158.65 L4183.98 3159.38 L4183.62 3160.47 L4182.89 3161.2 L4182.16 3161.56 L4181.07 3161.56 L4180.35 3161.2 L4179.62 3160.47 M 4190.75 3156.47L4190.75 3161.56 M 4190.75 3157.56L4190.02 3156.84 L4189.29 3156.47 L4188.2 3156.47 L4187.47 3156.84 L4186.75 3157.56 L4186.38 3158.65 L4186.38 3159.38 L4186.75 3160.47 L4187.47 3161.2 L4188.2 3161.56 L4189.29 3161.56 L4190.02 3161.2 L4190.75 3160.47 M 4193.15 3153.93L4193.15 3161.56 M 4193.15 3153.93L4195.69 3153.93 L4196.78 3154.29 L4197.51 3155.02 L4197.87 3155.75 L4198.24 3156.84 L4198.24 3158.65 L4197.87 3159.75 L4197.51 3160.47 L4196.78 3161.2 L4195.69 3161.56 L4193.15 3161.56 M 4200.64 3153.93L4201 3154.29 L4201.36 3153.93 L4201 3153.56 L4200.64 3153.93 M 4201 3156.47L4201 3161.56 M 4207.76 3157.56L4207.4 3156.84 L4206.31 3156.47 L4205.22 3156.47 L4204.13 3156.84 L4203.76 3157.56 L4204.13 3158.29 L4204.85 3158.65 L4206.67 3159.02 L4207.4 3159.38 L4207.76 3160.11 L4207.76 3160.47 L4207.4 3161.2 L4206.31 3161.56 L4205.22 3161.56 L4204.13 3161.2 L4203.76 3160.47 M 4210.16 3156.47L4210.16 3164.11 M 4210.16 3157.56L4210.89 3156.84 L4211.62 3156.47 L4212.71 3156.47 L4213.44 3156.84 L4214.16 3157.56 L4214.53 3158.65 L4214.53 3159.38 L4214.16 3160.47 L4213.44 3161.2 L4212.71 3161.56 L4211.62 3161.56 L4210.89 3161.2 L4210.16 3160.47 M 4216.93 3153.93L4216.93 3161.56 M 4223.69 3156.47L4223.69 3161.56 M 4223.69 3157.56L4222.96 3156.84 L4222.24 3156.47 L4221.15 3156.47 L4220.42 3156.84 L4219.69 3157.56 L4219.33 3158.65 L4219.33 3159.38 L4219.69 3160.47 L4220.42 3161.2 L4221.15 3161.56 L4222.24 3161.56 L4222.96 3161.2 L4223.69 3160.47 M 4226.45 3156.47L4228.64 3161.56 M 4230.82 3156.47L4228.64 3161.56 L4227.91 3163.02 L4227.18 3163.75 L4226.45 3164.11 L4226.09 3164.11 M 4233.22 3164.11L4239.76 3164.11 M 4242.16 3153.93L4245.07 3161.56 M 4247.98 3153.93L4245.07 3161.56 M 4250.38 3155.38L4251.11 3155.02 L4252.2 3153.93 L4252.2 3161.56 M 4254.96 3159.75L4254.6 3160.11 L4254.96 3160.47 L4255.33 3160.11 L4254.96 3159.75 M 4259.91 3153.93L4258.82 3154.29 L4258.09 3155.38 L4257.73 3157.2 L4257.73 3158.29 L4258.09 3160.11 L4258.82 3161.2 L4259.91 3161.56 L4260.64 3161.56 L4261.73 3161.2 L4262.45 3160.11 L4262.82 3158.29 L4262.82 3157.2 L4262.45 3155.38 L4261.73 3154.29 L4260.64 3153.93 L4259.91 3153.93 ","useTrueTypeFontRendering":false,"thickness":0.8,"width":0.8,"net":""}],"B":[{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4161,3130.2638 4135,3130.2638 4135,3127.3898 4129.0002,3127.3898 4129,3130.2641 4123,3130.2638 4123,3106.6418 4173,3106.6418"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4161,3130.2638 4171,3130.2638"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4173,3106.6418 4183,3106.6418"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4197,3130.3898 4197,3127.5158"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4203,3106.7677 4203,3130.3898"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4197,3127.5158 4191.0002,3127.5158"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4203,3130.5158 4197,3130.5158"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4183,3106.6418 4203,3106.6418"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4171,3130.2638 4191,3130.2638"},{"type":"polyline","net":"","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4191.0002,3127.5158 4191.0002,3130.2638"},{"type":"text","svgpath":"M 4189.88 3147.7999 L 4190.71 3146.3999 L 4189.99 3145.2699 L 4189.59 3145.2199 L 4189.59 3145.0699 L 4190.59 3145.0699 L 4190.59 3145.2199 L 4190.2 3145.2799 L 4190.8 3146.2499 L 4191.38 3145.2599 L 4190.97 3145.2199 L 4190.97 3145.0699 L 4192.2 3145.0699 L 4192.2 3145.2199 L 4191.82 3145.2599 L 4191.04 3146.5799 L 4191.82 3147.7899 L 4192.23 3147.8499 L 4192.23 3147.9999 L 4191.24 3147.9999 L 4191.24 3147.8499 L 4191.6 3147.7899 L 4190.95 3146.7299 L 4190.32 3147.7999 L 4190.73 3147.8499 L 4190.73 3147.9999 L 4189.51 3147.9999 L 4189.51 3147.8499 Z  M 4186.2 3145.2199 L 4186.2 3145.0699 L 4187.43 3145.0699 L 4187.43 3145.2199 L 4187.03 3145.2599 C 4187.02 3145.6399 4187.02 3146.0299 4187.02 3146.4099 L 4188.45 3146.4099 C 4188.45 3146.0199 4188.45 3145.6399 4188.44 3145.2599 L 4188.03 3145.2199 L 4188.03 3145.0699 L 4189.26 3145.0699 L 4189.26 3145.2199 L 4188.85 3145.2599 C 4188.85 3145.6499 4188.85 3146.0399 4188.85 3146.4299 L 4188.85 3146.6399 C 4188.85 3147.0399 4188.85 3147.4199 4188.85 3147.7999 L 4189.26 3147.8499 L 4189.26 3147.9999 L 4188.03 3147.9999 L 4188.03 3147.8499 L 4188.44 3147.7999 C 4188.45 3147.4199 4188.45 3147.0299 4188.45 3146.5799 L 4187.02 3146.5799 C 4187.02 3147.0399 4187.02 3147.4299 4187.03 3147.7999 L 4187.43 3147.8499 L 4187.43 3147.9999 L 4186.2 3147.9999 L 4186.2 3147.8499 L 4186.61 3147.7999 C 4186.62 3147.4199 4186.62 3147.0299 4186.62 3146.6399 L 4186.62 3146.4299 C 4186.62 3146.0399 4186.62 3145.6399 4186.61 3145.2599 Z  M 4185.51 3147.6599 C 4185.31 3147.4499 4185.11 3147.2499 4184.99 3147.1299 C 4184.34 3146.4399 4184.11 3146.1599 4184.11 3145.7799 C 4184.11 3145.3299 4184.37 3145.0099 4184.93 3145.0099 C 4185.37 3145.0099 4185.75 3145.2299 4185.81 3145.6699 C 4185.77 3145.7499 4185.69 3145.7999 4185.6 3145.7999 C 4185.49 3145.7999 4185.41 3145.7299 4185.36 3145.5299 L 4185.27 3145.2099 C 4185.18 3145.1899 4185.1 3145.1799 4185.03 3145.1799 C 4184.71 3145.1799 4184.5 3145.4299 4184.5 3145.7999 C 4184.5 3146.1599 4184.7 3146.4899 4185.13 3146.9799 C 4185.32 3147.1999 4185.55 3147.4599 4185.79 3147.7299 L 4185.79 3147.9999 L 4183.99 3147.9999 L 4183.99 3147.6599 Z  M 4183.15 3148.0599 C 4182.99 3148.0599 4182.85 3147.9199 4182.85 3147.7599 C 4182.85 3147.5999 4182.99 3147.4599 4183.15 3147.4599 C 4183.32 3147.4599 4183.45 3147.5999 4183.45 3147.7599 C 4183.45 3147.9199 4183.32 3148.0599 4183.15 3148.0599 Z  M 4181.83 3145.4099 L 4180.57 3145.4099 L 4180.57 3145.0699 L 4182 3145.0699 L 4182.09 3146.4399 L 4181.98 3146.4699 C 4181.84 3146.4299 4181.69 3146.4099 4181.56 3146.4099 C 4181.14 3146.4099 4180.87 3146.6699 4180.87 3147.1299 C 4180.87 3147.5899 4181.11 3147.8899 4181.53 3147.8899 C 4181.63 3147.8899 4181.72 3147.8799 4181.81 3147.8499 L 4181.88 3147.5799 C 4181.93 3147.3699 4181.99 3147.3099 4182.12 3147.3099 C 4182.21 3147.3099 4182.29 3147.3599 4182.33 3147.4499 C 4182.24 3147.8499 4181.95 3148.0599 4181.51 3148.0599 C 4180.89 3148.0599 4180.49 3147.6699 4180.49 3147.0999 C 4180.49 3146.5099 4180.87 3146.1799 4181.44 3146.1799 C 4181.6 3146.1799 4181.74 3146.1999 4181.89 3146.2399 Z  M 4179.96 3146.8299 L 4178.99 3145.4399 L 4178.99 3146.8299 Z  M 4178.17 3146.8299 L 4178.64 3146.8299 L 4178.64 3145.0199 L 4178.88 3145.0199 L 4180.18 3146.8799 L 4180.18 3147.0899 L 4178.99 3147.0899 L 4178.99 3147.9999 L 4178.64 3147.9999 L 4178.64 3147.0899 L 4178.17 3147.0899 Z  M 4177.93 3147.0299 L 4176.91 3147.0299 L 4176.91 3146.7699 L 4177.93 3146.7699 Z  M 4176.51 3145.0699 L 4176.51 3145.4099 L 4174.97 3145.4099 L 4176.14 3147.9599 L 4176.1 3147.9999 L 4175.77 3147.9999 L 4174.73 3145.2799 L 4174.73 3145.0699 Z  M 4173.23 3145.2399 C 4172.71 3145.2399 4172.47 3145.4899 4172.47 3145.9399 C 4172.47 3146.3599 4172.69 3146.6499 4173.24 3146.6499 L 4173.52 3146.6499 L 4173.52 3146.4299 C 4173.52 3146.0299 4173.52 3145.6299 4173.51 3145.2399 Z  M 4173.29 3146.8299 C 4172.41 3146.8299 4172.06 3146.4199 4172.06 3145.9399 C 4172.06 3145.4199 4172.43 3145.0699 4173.16 3145.0699 L 4174.34 3145.0699 L 4174.34 3145.2199 L 4173.93 3145.2599 C 4173.92 3145.6499 4173.92 3146.0399 4173.92 3146.4299 L 4173.92 3146.6399 C 4173.92 3147.0399 4173.92 3147.4199 4173.93 3147.7999 L 4174.34 3147.8499 L 4174.34 3147.9999 L 4173.1 3147.9999 L 4173.1 3147.8499 L 4173.51 3147.7999 C 4173.52 3147.4699 4173.52 3147.1499 4173.52 3146.8299 Z  M 4169.75 3147.5999 L 4168.11 3147.5999 L 4168.11 3148.0399 L 4169.75 3148.0399 Z  M 4168.11 3145.8999 L 4168.11 3146.3399 L 4169.75 3146.3399 L 4169.75 3145.8999 Z  M 4168.11 3147.0299 L 4168.11 3147.4799 L 4169.75 3147.4799 L 4169.75 3147.0299 Z  M 4168.11 3146.9099 L 4169.75 3146.9099 L 4169.75 3146.4599 L 4168.11 3146.4599 Z  M 4167.67 3148.0399 L 4167.78 3148.0399 L 4167.78 3145.9499 C 4167.68 3145.9299 4167.62 3145.9099 4167.59 3145.8699 L 4167.99 3145.5799 L 4168.15 3145.7899 L 4169.05 3145.7899 C 4169.01 3145.6599 4168.96 3145.5199 4168.92 3145.3699 L 4167.26 3145.3699 C 4167.21 3145.3699 4167.17 3145.3499 4167.16 3145.2999 C 4167.31 3145.1699 4167.57 3144.9799 4167.57 3144.9799 L 4167.79 3145.2499 L 4168.89 3145.2499 C 4168.84 3145.0799 4168.79 3144.9199 4168.76 3144.7799 C 4168.67 3144.7799 4168.63 3144.7399 4168.61 3144.6799 L 4169.12 3144.6099 C 4169.13 3144.7999 4169.16 3145.0299 4169.19 3145.2499 L 4170.68 3145.2499 L 4170.65 3145.3699 L 4169.2 3145.3699 C 4169.22 3145.5199 4169.24 3145.6699 4169.25 3145.7899 L 4169.7 3145.7899 L 4170.07 3145.6399 L 4170.07 3148.0399 L 4170.75 3148.0399 L 4170.71 3148.1599 L 4167.17 3148.1599 C 4167.11 3148.1599 4167.07 3148.1399 4167.06 3148.0999 C 4167.21 3147.9599 4167.46 3147.7699 4167.46 3147.7699 Z  M 4165.15 3147.1599 L 4164.68 3147.1599 C 4164.63 3147.1599 4164.59 3147.1399 4164.58 3147.0999 C 4164.68 3146.9899 4164.84 3146.8399 4164.84 3146.8399 L 4164.98 3147.0399 L 4165.15 3147.0399 L 4165.15 3146.3699 C 4164.94 3146.3199 4164.7 3146.2499 4164.58 3146.1999 C 4164.53 3146.2199 4164.5 3146.2199 4164.48 3146.2099 L 4164.48 3147.8799 L 4165.15 3147.8799 Z  M 4163.57 3146.2299 L 4164.03 3146.2299 L 4164 3146.3499 L 4163.53 3146.3499 L 4163.53 3147.0399 L 4164.02 3147.0399 L 4163.98 3147.1599 L 4163.53 3147.1599 L 4163.53 3147.8799 L 4164.17 3147.8799 L 4164.17 3145.7399 L 4163.16 3145.7399 C 4163.11 3145.7399 4163.07 3145.7199 4163.06 3145.6799 C 4163.2 3145.5399 4163.43 3145.3599 4163.43 3145.3599 L 4163.64 3145.6199 L 4164.17 3145.6199 L 4164.17 3145.0899 C 4163.89 3145.0399 4163.64 3144.9999 4163.43 3144.9399 C 4163.33 3144.9899 4163.25 3144.9799 4163.22 3144.9499 L 4163.55 3144.6399 C 4163.97 3144.8199 4164.79 3145.0599 4165.45 3145.1699 L 4165.44 3145.2399 C 4165.13 3145.2199 4164.79 3145.1799 4164.48 3145.1399 L 4164.48 3145.6199 L 4165.42 3145.6199 C 4165.39 3145.6099 4165.36 3145.5899 4165.36 3145.5599 C 4165.47 3145.4299 4165.66 3145.2499 4165.66 3145.2499 L 4165.83 3145.5099 L 4165.94 3145.5099 L 4165.94 3144.7899 C 4165.85 3144.7799 4165.81 3144.7399 4165.8 3144.6799 L 4166.24 3144.6299 L 4166.24 3145.5099 L 4166.79 3145.5099 L 4166.75 3145.6199 L 4166.24 3145.6199 L 4166.24 3146.4899 C 4166.49 3146.5599 4166.69 3146.6099 4166.81 3146.6299 L 4166.64 3147.0299 C 4166.6 3147.0199 4166.57 3146.9799 4166.55 3146.9299 C 4166.44 3146.8799 4166.34 3146.8199 4166.24 3146.7699 L 4166.24 3147.8799 C 4166.24 3147.9399 4166.26 3147.9599 4166.33 3147.9599 C 4166.4 3147.9599 4166.73 3147.9299 4166.73 3147.9299 L 4166.73 3147.9899 C 4166.58 3148.0099 4166.49 3148.0499 4166.44 3148.0999 C 4166.39 3148.1499 4166.37 3148.2299 4166.37 3148.3199 C 4165.99 3148.2799 4165.94 3148.1399 4165.94 3147.8999 L 4165.94 3146.6099 C 4165.75 3146.4999 4165.59 3146.4099 4165.47 3146.3299 L 4165.48 3146.2799 C 4165.64 3146.3199 4165.79 3146.3699 4165.94 3146.4099 L 4165.94 3145.6199 L 4165.53 3145.6199 L 4165.5 3145.7399 L 4164.48 3145.7399 L 4164.48 3146.1899 L 4164.74 3145.9199 C 4164.81 3145.9999 4164.97 3146.1399 4165.1 3146.2499 L 4165.44 3146.1399 L 4165.44 3148.3099 L 4165.4 3148.3099 C 4165.23 3148.3099 4165.15 3148.2399 4165.15 3148.2099 L 4165.15 3147.9999 L 4163.53 3147.9999 L 4163.53 3148.2799 L 4163.49 3148.2799 C 4163.38 3148.2799 4163.23 3148.2099 4163.23 3148.1799 L 4163.23 3146.3899 C 4163.15 3146.3799 4163.1 3146.3399 4163.08 3146.3199 L 4163.41 3146.0599 Z ","useTrueTypeFontRendering":true,"thickness":0.6,"width":0.6,"net":"","val":1},{"type":"text","svgpath":"M 4166.07 3135.9098 L 4165.86 3136.3198 L 4165.45 3136.7298 L 4165.05 3136.9298 L 4164.23 3136.9298 L 4163.82 3136.7298 L 4163.41 3136.3198 L 4163.2 3135.9098 L 4163 3135.2898 L 4163 3134.2698 L 4163.2 3133.6598 L 4163.41 3133.2498 L 4163.82 3132.8398 L 4164.23 3132.6398 L 4165.05 3132.6398 L 4165.45 3132.8398 L 4165.86 3133.2498 L 4166.07 3133.6598 M 4167.42 3136.9298 L 4167.42 3132.6398 M 4167.42 3136.9298 L 4170.28 3132.6398 M 4170.28 3136.9298 L 4170.28 3132.6398 M 4171.84 3135.9098 L 4171.84 3136.1098 L 4172.04 3136.5198 L 4172.25 3136.7298 L 4172.65 3136.9298 L 4173.47 3136.9298 L 4173.88 3136.7298 L 4174.09 3136.5198 L 4174.29 3136.1098 L 4174.29 3135.6998 L 4174.09 3135.2898 L 4173.68 3134.6798 L 4171.63 3132.6398 L 4174.5 3132.6398","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":"","ref":1},{"type":"text","svgpath":"M 4131.4818 3094.5682 L 4131.0727 3094.3636 L 4130.6636 3093.9545 L 4130.4591 3093.5455 L 4130.4591 3092.7273 L 4130.6636 3092.3182 L 4131.0727 3091.9091 L 4131.4818 3091.7045 L 4132.0955 3091.5 L 4133.1182 3091.5 L 4133.7318 3091.7045 L 4134.1409 3091.9091 L 4134.55 3092.3182 L 4134.7545 3092.7273 L 4134.7545 3093.5455 L 4134.55 3093.9545 L 4134.1409 3094.3636 L 4133.7318 3094.5682 L 4133.1182 3094.5682 M 4133.1182 3093.5455 L 4133.1182 3094.5682 M 4130.4591 3095.9182 L 4134.7545 3095.9182 M 4130.4591 3095.9182 L 4134.7545 3098.7818 M 4130.4591 3098.7818 L 4134.7545 3098.7818 M 4130.4591 3100.1318 L 4134.7545 3100.1318 M 4130.4591 3100.1318 L 4130.4591 3101.5636 L 4130.6636 3102.1773 L 4131.0727 3102.5864 L 4131.4818 3102.7909 L 4132.0955 3102.9955 L 4133.1182 3102.9955 L 4133.7318 3102.7909 L 4134.1409 3102.5864 L 4134.55 3102.1773 L 4134.7545 3101.5636 L 4134.7545 3100.1318","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":""},{"type":"text","svgpath":"M 4140.9591 3091.9091 L 4140.9591 3094.1591 L 4142.5955 3092.9318 L 4142.5955 3093.5455 L 4142.8 3093.9545 L 4143.0045 3094.1591 L 4143.6182 3094.3636 L 4144.0273 3094.3636 L 4144.6409 3094.1591 L 4145.05 3093.75 L 4145.2545 3093.1364 L 4145.2545 3092.5227 L 4145.05 3091.9091 L 4144.8455 3091.7045 L 4144.4364 3091.5 M 4140.9591 3095.7136 L 4145.2545 3097.35 M 4140.9591 3098.9864 L 4145.2545 3097.35 M 4140.9591 3100.7455 L 4140.9591 3102.9955 L 4142.5955 3101.7682 L 4142.5955 3102.3818 L 4142.8 3102.7909 L 4143.0045 3102.9955 L 4143.6182 3103.2 L 4144.0273 3103.2 L 4144.6409 3102.9955 L 4145.05 3102.5864 L 4145.2545 3101.9727 L 4145.2545 3101.3591 L 4145.05 3100.7455 L 4144.8455 3100.5409 L 4144.4364 3100.3364","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":""},{"type":"text","svgpath":"M 4151.0727 3094.3636 L 4150.6636 3093.9545 L 4150.4591 3093.3409 L 4150.4591 3092.5227 L 4150.6636 3091.9091 L 4151.0727 3091.5 L 4151.4818 3091.5 L 4151.8909 3091.7045 L 4152.0955 3091.9091 L 4152.3 3092.3182 L 4152.7091 3093.5455 L 4152.9136 3093.9545 L 4153.1182 3094.1591 L 4153.5273 3094.3636 L 4154.1409 3094.3636 L 4154.55 3093.9545 L 4154.7545 3093.3409 L 4154.7545 3092.5227 L 4154.55 3091.9091 L 4154.1409 3091.5 M 4151.4818 3098.7818 L 4151.0727 3098.5773 L 4150.6636 3098.1682 L 4150.4591 3097.7591 L 4150.4591 3096.9409 L 4150.6636 3096.5318 L 4151.0727 3096.1227 L 4151.4818 3095.9182 L 4152.0955 3095.7136 L 4153.1182 3095.7136 L 4153.7318 3095.9182 L 4154.1409 3096.1227 L 4154.55 3096.5318 L 4154.7545 3096.9409 L 4154.7545 3097.7591 L 4154.55 3098.1682 L 4154.1409 3098.5773 L 4153.7318 3098.7818 M 4150.4591 3100.1318 L 4154.7545 3100.1318 M 4154.7545 3100.1318 L 4154.7545 3102.5864","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":""},{"type":"text","svgpath":"M 4161.0727 3094.3636 L 4160.6636 3093.9545 L 4160.4591 3093.3409 L 4160.4591 3092.5227 L 4160.6636 3091.9091 L 4161.0727 3091.5 L 4161.4818 3091.5 L 4161.8909 3091.7045 L 4162.0955 3091.9091 L 4162.3 3092.3182 L 4162.7091 3093.5455 L 4162.9136 3093.9545 L 4163.1182 3094.1591 L 4163.5273 3094.3636 L 4164.1409 3094.3636 L 4164.55 3093.9545 L 4164.7545 3093.3409 L 4164.7545 3092.5227 L 4164.55 3091.9091 L 4164.1409 3091.5 M 4160.4591 3095.7136 L 4164.7545 3095.7136 M 4160.4591 3095.7136 L 4160.4591 3097.1455 L 4160.6636 3097.7591 L 4161.0727 3098.1682 L 4161.4818 3098.3727 L 4162.0955 3098.5773 L 4163.1182 3098.5773 L 4163.7318 3098.3727 L 4164.1409 3098.1682 L 4164.55 3097.7591 L 4164.7545 3097.1455 L 4164.7545 3095.7136 M 4160.4591 3101.5636 L 4164.7545 3099.9273 M 4160.4591 3101.5636 L 4164.7545 3103.2 M 4163.3227 3100.5409 L 4163.3227 3102.5864","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":""},{"type":"text","svgpath":"M 4171.5727 3094.3636 L 4171.1636 3093.9545 L 4170.9591 3093.3409 L 4170.9591 3092.5227 L 4171.1636 3091.9091 L 4171.5727 3091.5 L 4171.9818 3091.5 L 4172.3909 3091.7045 L 4172.5955 3091.9091 L 4172.8 3092.3182 L 4173.2091 3093.5455 L 4173.4136 3093.9545 L 4173.6182 3094.1591 L 4174.0273 3094.3636 L 4174.6409 3094.3636 L 4175.05 3093.9545 L 4175.2545 3093.3409 L 4175.2545 3092.5227 L 4175.05 3091.9091 L 4174.6409 3091.5 M 4170.9591 3095.7136 L 4175.2545 3096.7364 M 4170.9591 3097.7591 L 4175.2545 3096.7364 M 4170.9591 3097.7591 L 4175.2545 3098.7818 M 4170.9591 3099.8045 L 4175.2545 3098.7818","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":""},{"type":"text","svgpath":"M 4181.4591 3091.5 L 4185.7545 3091.5 M 4181.4591 3091.5 L 4181.4591 3093.3409 L 4181.6636 3093.9545 L 4181.8682 3094.1591 L 4182.2773 3094.3636 L 4182.6864 3094.3636 L 4183.0955 3094.1591 L 4183.3 3093.9545 L 4183.5045 3093.3409 M 4183.5045 3091.5 L 4183.5045 3093.3409 L 4183.7091 3093.9545 L 4183.9136 3094.1591 L 4184.3227 3094.3636 L 4184.9364 3094.3636 L 4185.3455 3094.1591 L 4185.55 3093.9545 L 4185.7545 3093.3409 L 4185.7545 3091.5","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":""},{"type":"text","svgpath":"M 4191.4591 3093.1364 L 4195.7545 3091.5 M 4191.4591 3093.1364 L 4195.7545 3094.7727 M 4194.3227 3092.1136 L 4194.3227 3094.1591","useTrueTypeFontRendering":false,"thickness":0.6,"width":0.6,"net":""}]},"fabrication":{"F":[],"B":[]}},"footprints":[{"ref":"CN2","center":[4163,3120.5],"bbox":{"pos":[4163,3120.5],"angle":180,"relpos":[-40,-10.015799999999672],"size":[80,23.87400000000025]},"pads":[{"layers":["F","B"],"pos":[4193,3120.5],"size":[7.0866,7.0866],"angle":-180,"shape":"oval","type":"th","drillsize":[3.937,4.1338],"drillshape":"oblong","holeCenterPoint":{"x":4193,"y":3120.5},"polygon":[],"net":"SWA"},{"layers":["F","B"],"pos":[4183,3120.5],"size":[7.0866,7.0866],"angle":-180,"shape":"oval","type":"th","drillsize":[3.937,4.1338],"drillshape":"oblong","holeCenterPoint":{"x":4183,"y":3120.5},"polygon":[],"net":"SWB"},{"layers":["F","B"],"pos":[4173,3120.5],"size":[7.0866,7.0866],"angle":-180,"shape":"oval","type":"th","drillsize":[3.937,4.1338],"drillshape":"oblong","holeCenterPoint":{"x":4173,"y":3120.5},"polygon":[],"net":"SW"},{"layers":["F","B"],"pos":[4133,3120.5],"size":[7.0866,6.2],"angle":-180,"pin1":1,"shape":"rect","type":"th","drillsize":[3.937,4.1338],"drillshape":"oblong","holeCenterPoint":{"x":4133,"y":3120.5},"polygon":[{"x":4129.4567,"y":3123.6},{"x":4136.5433,"y":3123.6},{"x":4136.5433,"y":3117.4},{"x":4129.4567,"y":3117.4}],"net":"GND"},{"layers":["F","B"],"pos":[4143,3120.5],"size":[7.0866,7.0866],"angle":-180,"shape":"oval","type":"th","drillsize":[3.937,4.1338],"drillshape":"oblong","holeCenterPoint":{"x":4143,"y":3120.5},"polygon":[],"net":"3.3V"},{"layers":["F","B"],"pos":[4153,3120.5],"size":[7.0866,7.0866],"angle":-180,"shape":"oval","type":"th","drillsize":[3.937,4.1338],"drillshape":"oblong","holeCenterPoint":{"x":4153,"y":3120.5},"polygon":[],"net":"SCL"},{"layers":["F","B"],"pos":[4163,3120.5],"size":[7.0866,7.0866],"angle":-180,"shape":"oval","type":"th","drillsize":[3.937,4.1338],"drillshape":"oblong","holeCenterPoint":{"x":4163,"y":3120.5},"polygon":[],"net":"SDA"}],"drawings":[],"layer":"B"},{"ref":"C3","center":[4216,3119],"bbox":{"pos":[4216,3119],"angle":0,"relpos":[-5.118499999999585,-2.0140000000001237],"size":[10.23699999999917,4.021799999999985]},"pads":[{"layers":["F"],"pos":[4212.85,3119],"size":[3.1496,3.1496],"angle":0,"pin1":1,"shape":"rect","type":"smd","drillsize":[0,0],"holeCenterPoint":{"x":4212.8503,"y":3119},"polygon":[{"x":4211.2755,"y":3117.4252},{"x":4214.4251,"y":3117.4252},{"x":4214.4251,"y":3120.5748},{"x":4211.2755,"y":3120.5748}],"net":"GND"},{"layers":["F"],"pos":[4219.15,3119],"size":[3.1496,3.1496],"angle":0,"shape":"rect","type":"smd","drillsize":[0,0],"holeCenterPoint":{"x":4219.1497,"y":3119},"polygon":[{"x":4217.5749,"y":3117.4252},{"x":4220.7245,"y":3117.4252},{"x":4220.7245,"y":3120.5748},{"x":4217.5749,"y":3120.5748}],"net":"SW"}],"drawings":[],"layer":"F"},{"ref":"C8","center":[4216,3128.5],"bbox":{"pos":[4216,3128.5],"angle":180,"relpos":[-5.118499999999585,-2.013999999999669],"size":[10.23699999999917,4.021799999999985]},"pads":[{"layers":["F"],"pos":[4219.15,3128.5],"size":[3.1496,3.1496],"angle":-180,"pin1":1,"shape":"rect","type":"smd","drillsize":[0,0],"holeCenterPoint":{"x":4219.1497,"y":3128.5},"polygon":[{"x":4220.7245,"y":3130.0748},{"x":4217.5749,"y":3130.0748},{"x":4217.5749,"y":3126.9252},{"x":4220.7245,"y":3126.9252}],"net":"SWB"},{"layers":["F"],"pos":[4212.85,3128.5],"size":[3.1496,3.1496],"angle":-180,"shape":"rect","type":"smd","drillsize":[0,0],"holeCenterPoint":{"x":4212.8503,"y":3128.5},"polygon":[{"x":4214.4251,"y":3130.0748},{"x":4211.2755,"y":3130.0748},{"x":4211.2755,"y":3126.9252},{"x":4214.4251,"y":3126.9252}],"net":"GND"}],"drawings":[],"layer":"F"},{"ref":"C9","center":[4216,3108.5],"bbox":{"pos":[4216,3108.5],"angle":180,"relpos":[-5.118499999999585,-2.013999999999669],"size":[10.23699999999917,4.021799999999985]},"pads":[{"layers":["F"],"pos":[4219.15,3108.5],"size":[3.1496,3.1496],"angle":-180,"pin1":1,"shape":"rect","type":"smd","drillsize":[0,0],"holeCenterPoint":{"x":4219.1497,"y":3108.5},"polygon":[{"x":4220.7245,"y":3110.0748},{"x":4217.5749,"y":3110.0748},{"x":4217.5749,"y":3106.9252},{"x":4220.7245,"y":3106.9252}],"net":"SWA"},{"layers":["F"],"pos":[4212.85,3108.5],"size":[3.1496,3.1496],"angle":-180,"shape":"rect","type":"smd","drillsize":[0,0],"holeCenterPoint":{"x":4212.8503,"y":3108.5},"polygon":[{"x":4214.4251,"y":3110.0748},{"x":4211.2755,"y":3110.0748},{"x":4211.2755,"y":3106.9252},{"x":4214.4251,"y":3106.9252}],"net":"GND"}],"drawings":[],"layer":"F"},{"ref":"SW1","center":[4275,3118.5],"bbox":{"pos":[4275,3118.5],"angle":270,"relpos":[-29.921299999999974,-32.08629999999948],"size":[59.84259999999995,64.17259999999942]},"pads":[{"layers":["F","B"],"pos":[4303.543,3108.658],"size":[7.0866,7.0866],"angle":-270,"shape":"oval","type":"th","drillsize":[4.7244,4.7244],"holeCenterPoint":{"x":4303.543,"y":3108.658},"polygon":[],"net":"GND"},{"layers":["F","B"],"pos":[4303.543,3128.343],"size":[7.0866,7.0866],"angle":-270,"shape":"oval","type":"th","drillsize":[4.7244,4.7244],"holeCenterPoint":{"x":4303.543,"y":3128.343},"polygon":[],"net":"SW"},{"layers":["F","B"],"pos":[4246.457,3108.658],"size":[7.0866,7.0866],"angle":-270,"pin1":1,"shape":"oval","type":"th","drillsize":[4.7244,4.7244],"holeCenterPoint":{"x":4246.457,"y":3108.658},"polygon":[],"net":"SWA"},{"layers":["F","B"],"pos":[4246.457,3118.5],"size":[7.0866,7.0866],"angle":-270,"shape":"oval","type":"th","drillsize":[4.7244,4.7244],"holeCenterPoint":{"x":4246.457,"y":3118.5},"polygon":[],"net":"GND"},{"layers":["F","B"],"pos":[4246.457,3128.343],"size":[7.0866,7.0866],"angle":-270,"shape":"oval","type":"th","drillsize":[4.7244,4.7244],"holeCenterPoint":{"x":4246.457,"y":3128.343},"polygon":[],"net":"SWB"},{"layers":["F","B"],"pos":[4275.984,3096.059],"size":[9.4488,14.9606],"angle":-270,"shape":"oval","type":"th","drillsize":[5.5118,9.4488],"drillshape":"oblong","holeCenterPoint":{"x":4275.984,"y":3096.0591},"polygon":[{"x":4273.2281,"y":3100.7834},{"x":4272.9926,"y":3100.7775},{"x":4272.7577,"y":3100.7599},{"x":4272.524,"y":3100.7306},{"x":4272.292,"y":3100.6897},{"x":4272.0623,"y":3100.6373},{"x":4271.8356,"y":3100.5735},{"x":4271.6123,"y":3100.4985},{"x":4271.393,"y":3100.4124},{"x":4271.1783,"y":3100.3155},{"x":4270.9686,"y":3100.2081},{"x":4270.7646,"y":3100.0903},{"x":4270.5668,"y":3099.9625},{"x":4270.3755,"y":3099.825},{"x":4270.1913,"y":3099.6781},{"x":4270.0147,"y":3099.5222},{"x":4269.8461,"y":3099.3578},{"x":4269.6858,"y":3099.1851},{"x":4269.5344,"y":3099.0046},{"x":4269.3922,"y":3098.8168},{"x":4269.2595,"y":3098.6222},{"x":4269.1366,"y":3098.4212},{"x":4269.024,"y":3098.2143},{"x":4268.9218,"y":3098.0021},{"x":4268.8303,"y":3097.785},{"x":4268.7497,"y":3097.5637},{"x":4268.6803,"y":3097.3386},{"x":4268.6222,"y":3097.1103},{"x":4268.5755,"y":3096.8794},{"x":4268.5404,"y":3096.6464},{"x":4268.5169,"y":3096.4121},{"x":4268.5052,"y":3096.1768},{"x":4268.5052,"y":3095.9412},{"x":4268.5169,"y":3095.7059},{"x":4268.5404,"y":3095.4716},{"x":4268.5755,"y":3095.2386},{"x":4268.6222,"y":3095.0077},{"x":4268.6803,"y":3094.7794},{"x":4268.7497,"y":3094.5543},{"x":4268.8303,"y":3094.333},{"x":4268.9218,"y":3094.1159},{"x":4269.024,"y":3093.9037},{"x":4269.1366,"y":3093.6968},{"x":4269.2595,"y":3093.4958},{"x":4269.3922,"y":3093.3012},{"x":4269.5344,"y":3093.1134},{"x":4269.6858,"y":3092.9329},{"x":4269.8461,"y":3092.7602},{"x":4270.0147,"y":3092.5958},{"x":4270.1913,"y":3092.4399},{"x":4270.3755,"y":3092.293},{"x":4270.5668,"y":3092.1555},{"x":4270.7646,"y":3092.0277},{"x":4270.9686,"y":3091.9099},{"x":4271.1783,"y":3091.8025},{"x":4271.393,"y":3091.7056},{"x":4271.6123,"y":3091.6195},{"x":4271.8356,"y":3091.5445},{"x":4272.0623,"y":3091.4807},{"x":4272.292,"y":3091.4283},{"x":4272.524,"y":3091.3874},{"x":4272.7577,"y":3091.3581},{"x":4272.9926,"y":3091.3405},{"x":4273.2281,"y":3091.3346},{"x":4278.7399,"y":3091.3346},{"x":4278.9754,"y":3091.3405},{"x":4279.2103,"y":3091.3581},{"x":4279.444,"y":3091.3874},{"x":4279.676,"y":3091.4283},{"x":4279.9057,"y":3091.4807},{"x":4280.1324,"y":3091.5445},{"x":4280.3557,"y":3091.6195},{"x":4280.575,"y":3091.7056},{"x":4280.7897,"y":3091.8025},{"x":4280.9994,"y":3091.9099},{"x":4281.2034,"y":3092.0277},{"x":4281.4012,"y":3092.1555},{"x":4281.5925,"y":3092.293},{"x":4281.7767,"y":3092.4399},{"x":4281.9533,"y":3092.5958},{"x":4282.1219,"y":3092.7602},{"x":4282.2822,"y":3092.9329},{"x":4282.4336,"y":3093.1134},{"x":4282.5758,"y":3093.3012},{"x":4282.7085,"y":3093.4958},{"x":4282.8314,"y":3093.6968},{"x":4282.944,"y":3093.9037},{"x":4283.0462,"y":3094.1159},{"x":4283.1377,"y":3094.333},{"x":4283.2183,"y":3094.5543},{"x":4283.2877,"y":3094.7794},{"x":4283.3458,"y":3095.0077},{"x":4283.3925,"y":3095.2386},{"x":4283.4276,"y":3095.4716},{"x":4283.4511,"y":3095.7059},{"x":4283.4628,"y":3095.9412},{"x":4283.4628,"y":3096.1768},{"x":4283.4511,"y":3096.4121},{"x":4283.4276,"y":3096.6464},{"x":4283.3925,"y":3096.8794},{"x":4283.3458,"y":3097.1103},{"x":4283.2877,"y":3097.3386},{"x":4283.2183,"y":3097.5637},{"x":4283.1377,"y":3097.785},{"x":4283.0462,"y":3098.0021},{"x":4282.944,"y":3098.2143},{"x":4282.8314,"y":3098.4212},{"x":4282.7085,"y":3098.6222},{"x":4282.5758,"y":3098.8168},{"x":4282.4336,"y":3099.0046},{"x":4282.2822,"y":3099.1851},{"x":4282.1219,"y":3099.3578},{"x":4281.9533,"y":3099.5222},{"x":4281.7767,"y":3099.6781},{"x":4281.5925,"y":3099.825},{"x":4281.4012,"y":3099.9625},{"x":4281.2034,"y":3100.0903},{"x":4280.9994,"y":3100.2081},{"x":4280.7897,"y":3100.3155},{"x":4280.575,"y":3100.4124},{"x":4280.3557,"y":3100.4985},{"x":4280.1324,"y":3100.5735},{"x":4279.9057,"y":3100.6373},{"x":4279.676,"y":3100.6897},{"x":4279.444,"y":3100.7306},{"x":4279.2103,"y":3100.7599},{"x":4278.9754,"y":3100.7775},{"x":4278.7399,"y":3100.7834}],"net":""},{"layers":["F","B"],"pos":[4275.984,3140.941],"size":[9.4488,14.9606],"angle":-270,"shape":"oval","type":"th","drillsize":[5.5118,9.4488],"drillshape":"oblong","holeCenterPoint":{"x":4275.984,"y":3140.9409},"polygon":[{"x":4273.2281,"y":3145.6654},{"x":4272.9926,"y":3145.6595},{"x":4272.7577,"y":3145.6419},{"x":4272.524,"y":3145.6126},{"x":4272.292,"y":3145.5717},{"x":4272.0623,"y":3145.5193},{"x":4271.8356,"y":3145.4555},{"x":4271.6123,"y":3145.3805},{"x":4271.393,"y":3145.2944},{"x":4271.1783,"y":3145.1975},{"x":4270.9686,"y":3145.0901},{"x":4270.7646,"y":3144.9723},{"x":4270.5668,"y":3144.8445},{"x":4270.3755,"y":3144.707},{"x":4270.1913,"y":3144.5601},{"x":4270.0147,"y":3144.4042},{"x":4269.8461,"y":3144.2398},{"x":4269.6858,"y":3144.0671},{"x":4269.5344,"y":3143.8866},{"x":4269.3922,"y":3143.6988},{"x":4269.2595,"y":3143.5042},{"x":4269.1366,"y":3143.3032},{"x":4269.024,"y":3143.0963},{"x":4268.9218,"y":3142.8841},{"x":4268.8303,"y":3142.667},{"x":4268.7497,"y":3142.4457},{"x":4268.6803,"y":3142.2206},{"x":4268.6222,"y":3141.9923},{"x":4268.5755,"y":3141.7614},{"x":4268.5404,"y":3141.5284},{"x":4268.5169,"y":3141.2941},{"x":4268.5052,"y":3141.0588},{"x":4268.5052,"y":3140.8232},{"x":4268.5169,"y":3140.5879},{"x":4268.5404,"y":3140.3536},{"x":4268.5755,"y":3140.1206},{"x":4268.6222,"y":3139.8897},{"x":4268.6803,"y":3139.6614},{"x":4268.7497,"y":3139.4363},{"x":4268.8303,"y":3139.215},{"x":4268.9218,"y":3138.9979},{"x":4269.024,"y":3138.7857},{"x":4269.1366,"y":3138.5788},{"x":4269.2595,"y":3138.3778},{"x":4269.3922,"y":3138.1832},{"x":4269.5344,"y":3137.9954},{"x":4269.6858,"y":3137.8149},{"x":4269.8461,"y":3137.6422},{"x":4270.0147,"y":3137.4778},{"x":4270.1913,"y":3137.3219},{"x":4270.3755,"y":3137.175},{"x":4270.5668,"y":3137.0375},{"x":4270.7646,"y":3136.9097},{"x":4270.9686,"y":3136.7919},{"x":4271.1783,"y":3136.6845},{"x":4271.393,"y":3136.5876},{"x":4271.6123,"y":3136.5015},{"x":4271.8356,"y":3136.4265},{"x":4272.0623,"y":3136.3627},{"x":4272.292,"y":3136.3103},{"x":4272.524,"y":3136.2694},{"x":4272.7577,"y":3136.2401},{"x":4272.9926,"y":3136.2225},{"x":4273.2281,"y":3136.2166},{"x":4278.7399,"y":3136.2166},{"x":4278.9754,"y":3136.2225},{"x":4279.2103,"y":3136.2401},{"x":4279.444,"y":3136.2694},{"x":4279.676,"y":3136.3103},{"x":4279.9057,"y":3136.3627},{"x":4280.1324,"y":3136.4265},{"x":4280.3557,"y":3136.5015},{"x":4280.575,"y":3136.5876},{"x":4280.7897,"y":3136.6845},{"x":4280.9994,"y":3136.7919},{"x":4281.2034,"y":3136.9097},{"x":4281.4012,"y":3137.0375},{"x":4281.5925,"y":3137.175},{"x":4281.7767,"y":3137.3219},{"x":4281.9533,"y":3137.4778},{"x":4282.1219,"y":3137.6422},{"x":4282.2822,"y":3137.8149},{"x":4282.4336,"y":3137.9954},{"x":4282.5758,"y":3138.1832},{"x":4282.7085,"y":3138.3778},{"x":4282.8314,"y":3138.5788},{"x":4282.944,"y":3138.7857},{"x":4283.0462,"y":3138.9979},{"x":4283.1377,"y":3139.215},{"x":4283.2183,"y":3139.4363},{"x":4283.2877,"y":3139.6614},{"x":4283.3458,"y":3139.8897},{"x":4283.3925,"y":3140.1206},{"x":4283.4276,"y":3140.3536},{"x":4283.4511,"y":3140.5879},{"x":4283.4628,"y":3140.8232},{"x":4283.4628,"y":3141.0588},{"x":4283.4511,"y":3141.2941},{"x":4283.4276,"y":3141.5284},{"x":4283.3925,"y":3141.7614},{"x":4283.3458,"y":3141.9923},{"x":4283.2877,"y":3142.2206},{"x":4283.2183,"y":3142.4457},{"x":4283.1377,"y":3142.667},{"x":4283.0462,"y":3142.8841},{"x":4282.944,"y":3143.0963},{"x":4282.8314,"y":3143.3032},{"x":4282.7085,"y":3143.5042},{"x":4282.5758,"y":3143.6988},{"x":4282.4336,"y":3143.8866},{"x":4282.2822,"y":3144.0671},{"x":4282.1219,"y":3144.2398},{"x":4281.9533,"y":3144.4042},{"x":4281.7767,"y":3144.5601},{"x":4281.5925,"y":3144.707},{"x":4281.4012,"y":3144.8445},{"x":4281.2034,"y":3144.9723},{"x":4280.9994,"y":3145.0901},{"x":4280.7897,"y":3145.1975},{"x":4280.575,"y":3145.2944},{"x":4280.3557,"y":3145.3805},{"x":4280.1324,"y":3145.4555},{"x":4279.9057,"y":3145.5193},{"x":4279.676,"y":3145.5717},{"x":4279.444,"y":3145.6126},{"x":4279.2103,"y":3145.6419},{"x":4278.9754,"y":3145.6595},{"x":4278.7399,"y":3145.6654}],"net":""}],"drawings":[],"layer":"F"},{"ref":"U6","center":[4089,3095.5],"bbox":{"pos":[4089,3095.5],"angle":0,"relpos":[0,0],"size":[149.60599999999977,47.24400000000014]},"pads":[{"layers":["F","B"],"pos":[4094.906,3104.122],"size":[6,6],"angle":0,"pin1":1,"shape":"oval","type":"th","drillsize":[3.6,3.6],"holeCenterPoint":{"x":4094.9055,"y":3104.122},"polygon":[],"net":"SDA"},{"layers":["F","B"],"pos":[4094.906,3114.122],"size":[6,6],"angle":0,"shape":"oval","type":"th","drillsize":[3.6,3.6],"holeCenterPoint":{"x":4094.9055,"y":3114.122},"polygon":[],"net":"SCL"},{"layers":["F","B"],"pos":[4094.906,3124.122],"size":[6,6],"angle":0,"shape":"oval","type":"th","drillsize":[3.6,3.6],"holeCenterPoint":{"x":4094.9055,"y":3124.122},"polygon":[],"net":"3.3V"},{"layers":["F","B"],"pos":[4094.906,3134.122],"size":[6,6],"angle":0,"shape":"oval","type":"th","drillsize":[3.6,3.6],"holeCenterPoint":{"x":4094.9055,"y":3134.122},"polygon":[],"net":"GND"}],"drawings":[],"layer":"F"}],"metadata":{"title":"PCB_HeaterDisplay","revision":"0","company":"Unknown Company","date":"2022-01-02"},"tracks":{"F":[{"type":"polyline","net":"SCL","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4153,3120.4998 4146.6222,3114.122 4094.906,3114.122"},{"type":"polyline","net":"SDA","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4163,3120.4998 4146.6222,3104.122 4094.906,3104.122"},{"type":"polyline","net":"SWA","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4193,3120.4998 4193,3109.5 4200,3102.5 4240.299,3102.5 4246.457,3108.658"},{"type":"polyline","net":"SWA","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4219.15,3108.5 4219.15,3102.5"},{"type":"polyline","net":"SWB","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4219.15,3128.5 4219.15,3135.5"},{"type":"polyline","net":"SW","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4303.54,3128.34 4259.84,3128.34 4255,3123.5 4242,3123.5 4237.5,3119 4219.15,3119"},{"type":"polyline","net":"SWB","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4183,3120.5 4183,3127.5 4191,3135.5 4239.3,3135.5 4246.46,3128.34"},{"type":"polyline","net":"SW","start":[0,0],"end":[0,0],"width":1,"svgpath":"M4173,3120.5 4180,3113.5 4185,3113.5 4188,3116.5 4188,3125.5 4189,3126.5 4204,3126.5 4206.5,3124 4217.5,3124 4219.15,3122.35 4219.15,3119"},{"type":"polyline","net":"GND","start":[0,0],"end":[0,0],"width":2,"svgpath":"M4212.85,3113.87 4212.85,3119"},{"type":"polyline","net":"GND","start":[0,0],"end":[0,0],"width":2,"svgpath":"M4212.85,3108.5 4212.85,3113.87"},{"type":"polyline","net":"GND","start":[0,0],"end":[0,0],"width":2,"svgpath":"M4212.85,3128.5 4212.85,3128.5 4208.5,3128.5"},{"type":"polygon","svgpath":"M4214.42529,3110.07471L4211.27539,3110.07471L4211.85003,3113.07471L4213.85003,3113.07471Z","start":[0,0],"end":[0,0],"net":"GND"},{"type":"polygon","svgpath":"M4217.8999,3106.92529L4220.3999,3106.92529L4219.6499,3105.42529L4218.6499,3105.42529Z","start":[0,0],"end":[0,0],"net":"SWA"},{"type":"polygon","svgpath":"M4211.27539,3130.07471L4211.27539,3126.92529L4208.5,3127.5L4208.5,3129.5Z","start":[0,0],"end":[0,0],"net":"GND"},{"type":"polygon","svgpath":"M4220.3999,3130.07471L4217.8999,3130.07471L4218.6499,3131.57471L4219.6499,3131.57471Z","start":[0,0],"end":[0,0],"net":"SWB"},{"type":"polygon","svgpath":"M4220.72461,3117.74976L4220.72461,3120.24976L4222.22461,3119.49976L4222.22461,3118.49976Z","start":[0,0],"end":[0,0],"net":"SW"},{"type":"polygon","svgpath":"M4220.40039,3120.57471L4217.90039,3120.57471L4218.65039,3122.07471L4219.65039,3122.07471Z","start":[0,0],"end":[0,0],"net":"SW"},{"type":"polygon","svgpath":"M4211.27539,3117.42529L4214.42529,3117.42529L4213.8501,3114.42529L4211.8501,3114.42529Z","start":[0,0],"end":[0,0],"net":"GND"},{"type":"polygon","svgpath":"M4211.9501,3114.66409L4213.7501,3114.66409L4213.8501,3115.50409L4211.8501,3115.50409Z","start":[0,0],"end":[0,0],"net":"GND"},{"type":"polygon","svgpath":"M4213.75003,3113.07655L4211.95003,3113.07672L4211.84995,3112.23673L4213.84995,3112.23654Z","start":[0,0],"end":[0,0],"net":"GND"},{"type":"polygon","svgpath":"M4209.29373,3129.4L4209.29373,3127.6L4210.13373,3127.5L4210.13373,3129.5Z","start":[0,0],"end":[0,0],"net":"GND"},{"type":"polygon","svgpath":"M4096.89032,3116.37207L4096.89032,3111.87207L4098.99032,3113.62207L4098.99032,3114.62207Z","start":[0,0],"end":[0,0],"net":"SCL"},{"type":"polygon","svgpath":"M4096.89032,3106.37207L4096.89032,3101.87207L4098.99032,3103.62207L4098.99032,3104.62207Z","start":[0,0],"end":[0,0],"net":"SDA"},{"type":"polygon","svgpath":"M4242.92069,3128.12107L4246.67886,3131.87937L4243.39945,3132.10759L4242.69235,3131.40047Z","start":[0,0],"end":[0,0],"net":"SWB"},{"type":"polygon","svgpath":"M4242.92069,3108.87992L4246.67885,3105.12161L4243.39944,3104.8934L4242.69235,3105.60052Z","start":[0,0],"end":[0,0],"net":"SWA"},{"type":"polygon","svgpath":"M4301.1993,3131.00049L4301.1993,3125.68554L4298.71899,3127.84302L4298.71899,3128.84302Z","start":[0,0],"end":[0,0],"net":"SW"},{"type":"polygon","svgpath":"M4159.46366,3120.72167L4163.22187,3116.96341L4159.94245,3116.73515L4159.23535,3117.44227Z","start":[0,0],"end":[0,0],"net":"SDA"},{"type":"polygon","svgpath":"M4149.46366,3120.72172L4153.22182,3116.96341L4149.94241,3116.73519L4149.23532,3117.44231Z","start":[0,0],"end":[0,0],"net":"SCL"},{"type":"polygon","svgpath":"M4172.77817,3116.96341L4176.53634,3120.72171L4176.76468,3117.4423L4176.05758,3116.73519Z","start":[0,0],"end":[0,0],"net":"SW"},{"type":"polygon","svgpath":"M4185.65747,3122.84343L4180.34253,3122.84343L4182.5,3125.32374L4183.5,3125.32374Z","start":[0,0],"end":[0,0],"net":"SWB"},{"type":"polygon","svgpath":"M4195.65747,3118.15608L4190.34253,3118.15608L4192.5,3115.67577L4193.5,3115.67577Z","start":[0,0],"end":[0,0],"net":"SWA"},{"start":[4208.5,3128.5],"end":[4208.5,3128.5],"width":2.4,"net":"GND"},{"start":[4212.85,3113.87],"end":[4212.85,3113.87],"width":2.4,"net":"GND"}],"B":[{"start":[4208.5,3128.5],"end":[4208.5,3128.5],"width":2.4,"net":"GND"},{"start":[4212.85,3113.87],"end":[4212.85,3113.87],"width":2.4,"net":"GND"}]},"zones":{"F":[{"net":"3.3V","svgpath":"M 4081.4919 3167.48 L 4081.32323 3167.4427 4081.18602 3167.33776 4081.10586 3167.18475 4081.09769 3167.0122 4081.16304 3166.8523 4081.28972 3166.73486 4081.4541 3166.68179 4081.75279 3166.65344 4082.74255 3166.48321 4083.7166 3166.23861 4084.66936 3165.92105 4085.59538 3165.53233 4086.48934 3165.0747 4087.34614 3164.55077 4088.16085 3163.96354 4088.92883 3163.31638 4089.64565 3162.61299 4090.30723 3161.85741 4090.90977 3161.05395 4091.44982 3160.20722 4091.92429 3159.32207 4092.33046 3158.40358 4092.666 3157.457 4092.92898 3156.48775 4093.11792 3155.5014 4093.23171 3154.50357 4093.26971 3153.5 4093.23171 3152.49643 4093.11792 3151.4986 4092.92898 3150.51225 4092.666 3149.543 4092.33046 3148.59642 4091.92429 3147.67793 4091.44982 3146.79278 4090.90977 3145.94605 4090.30723 3145.14259 4089.64565 3144.38701 4088.92883 3143.68362 4088.16085 3143.03646 4087.34614 3142.44923 4086.48934 3141.9253 4085.59538 3141.46767 4084.66936 3141.07895 4083.7166 3140.76139 4082.74255 3140.51679 4081.75279 3140.34656 4080.75299 3140.25167 4079.74888 3140.23266 4078.74621 3140.28965 4077.75072 3140.42231 4076.76811 3140.62987 4075.80401 3140.91116 4074.86395 3141.26455 4073.95331 3141.68802 4073.0773 3142.17915 4072.24095 3142.73513 4071.44904 3143.35277 4070.7061 3144.02853 4070.01641 3144.75854 4069.38389 3145.53862 4068.81219 3146.36431 4068.30456 3147.23086 4067.86393 3148.13333 4067.49282 3149.06653 4067.19334 3150.02513 4066.96722 3151.00364 4066.81542 3151.99854 4066.7549 3152.15694 4066.63418 3152.27603 4066.47498 3152.33441 4066.30589 3152.32159 4066.15731 3152.23986 4066.05594 3152.10393 4066.02 3151.93821 4066.02 3085.06179 4066.05594 3084.89607 4066.15731 3084.76014 4066.30589 3084.67841 4066.47498 3084.66559 4066.63418 3084.72397 4066.7549 3084.84306 4066.81542 3085.00146 4066.96722 3085.99636 4067.19334 3086.97487 4067.49282 3087.93347 4067.86393 3088.86667 4068.30456 3089.76914 4068.81219 3090.63569 4069.38389 3091.46138 4070.01641 3092.24146 4070.7061 3092.97147 4071.44904 3093.64723 4072.24095 3094.26487 4073.0773 3094.82085 4073.95331 3095.31198 4074.86395 3095.73545 4075.80401 3096.08884 4076.76811 3096.37013 4077.75072 3096.57769 4078.74621 3096.71035 4079.74888 3096.76734 4080.75299 3096.74833 4081.75279 3096.65344 4082.74255 3096.48321 4083.7166 3096.23861 4084.66936 3095.92105 4085.59538 3095.53233 4086.48934 3095.0747 4087.34614 3094.55077 4088.16085 3093.96354 4088.92883 3093.31638 4089.64565 3092.61299 4090.30723 3091.85741 4090.90977 3091.05395 4091.44982 3090.20722 4091.92429 3089.32207 4092.33046 3088.40358 4092.666 3087.457 4092.92898 3086.48775 4093.11792 3085.5014 4093.23171 3084.50357 4093.26971 3083.5 4093.23171 3082.49643 4093.11792 3081.4986 4092.92898 3080.51225 4092.666 3079.543 4092.33046 3078.59642 4091.92429 3077.67793 4091.44982 3076.79278 4090.90977 3075.94605 4090.30723 3075.14259 4089.64565 3074.38701 4088.92883 3073.68362 4088.16085 3073.03646 4087.34614 3072.44923 4086.48934 3071.9253 4085.59538 3071.46767 4084.66936 3071.07895 4083.7166 3070.76139 4082.74255 3070.51679 4081.75279 3070.34656 4081.4541 3070.31821 4081.28972 3070.26514 4081.16304 3070.1477 4081.09769 3069.9878 4081.10586 3069.81525 4081.18602 3069.66224 4081.32323 3069.5573 4081.4919 3069.52 4308.49193 3069.52 4308.65864 3069.55639 4308.795 3069.65895 4308.87623 3069.80901 4308.88752 3069.97926 4308.82683 3070.13873 4308.7052 3070.2584 4308.54477 3070.3165 4307.75072 3070.42231 4306.76811 3070.62987 4305.80401 3070.91116 4304.86395 3071.26455 4303.95331 3071.68802 4303.0773 3072.17915 4302.24095 3072.73513 4301.44904 3073.35277 4300.7061 3074.02853 4300.01641 3074.75854 4299.38389 3075.53862 4298.81219 3076.36431 4298.30456 3077.23086 4297.86393 3078.13333 4297.49282 3079.06653 4297.19334 3080.02513 4296.96722 3081.00364 4296.81574 3081.99644 4296.73979 3082.99785 4296.73979 3084.00215 4296.81574 3085.00356 4296.96722 3085.99636 4297.19334 3086.97487 4297.49282 3087.93347 4297.86393 3088.86667 4298.30456 3089.76914 4298.81219 3090.63569 4299.38389 3091.46138 4300.01641 3092.24146 4300.7061 3092.97147 4301.44904 3093.64723 4302.24095 3094.26487 4303.0773 3094.82085 4303.95331 3095.31198 4304.86395 3095.73545 4305.80401 3096.08884 4306.76811 3096.37013 4307.75072 3096.57769 4308.74621 3096.71035 4309.74888 3096.76734 4310.75299 3096.74833 4311.75279 3096.65344 4312.74255 3096.48321 4313.7166 3096.23861 4314.66936 3095.92105 4315.59538 3095.53233 4316.48934 3095.0747 4317.34614 3094.55077 4318.16085 3093.96354 4318.92883 3093.31638 4319.64565 3092.61299 4320.30723 3091.85741 4320.90977 3091.05395 4321.44982 3090.20722 4321.92429 3089.32207 4322.33046 3088.40358 4322.666 3087.457 4322.92898 3086.48775 4323.11792 3085.5014 4323.18258 3084.93441 4323.23818 3084.77198 4323.35676 3084.64782 4323.51647 3084.58481 4323.68787 3084.59455 4323.83941 3084.67525 4323.94316 3084.81205 4323.98 3084.97973 4323.98 3152.02027 4323.94316 3152.18795 4323.83941 3152.32475 4323.68787 3152.40545 4323.51647 3152.41519 4323.35676 3152.35218 4323.23818 3152.22802 4323.18258 3152.06559 4323.11792 3151.4986 4322.92898 3150.51225 4322.666 3149.543 4322.33046 3148.59642 4321.92429 3147.67793 4321.44982 3146.79278 4320.90977 3145.94605 4320.30723 3145.14259 4319.64565 3144.38701 4318.92883 3143.68362 4318.16085 3143.03646 4317.34614 3142.44923 4316.48934 3141.9253 4315.59538 3141.46767 4314.66936 3141.07895 4313.7166 3140.76139 4312.74255 3140.51679 4311.75279 3140.34656 4310.75299 3140.25167 4309.74888 3140.23266 4308.74621 3140.28965 4307.75072 3140.42231 4306.76811 3140.62987 4305.80401 3140.91116 4304.86395 3141.26455 4303.95331 3141.68802 4303.0773 3142.17915 4302.24095 3142.73513 4301.44904 3143.35277 4300.7061 3144.02853 4300.01641 3144.75854 4299.38389 3145.53862 4298.81219 3146.36431 4298.30456 3147.23086 4297.86393 3148.13333 4297.49282 3149.06653 4297.19334 3150.02513 4296.96722 3151.00364 4296.81574 3151.99644 4296.73979 3152.99785 4296.73979 3154.00215 4296.81574 3155.00356 4296.96722 3155.99636 4297.19334 3156.97487 4297.49282 3157.93347 4297.86393 3158.86667 4298.30456 3159.76914 4298.81219 3160.63569 4299.38389 3161.46138 4300.01641 3162.24146 4300.7061 3162.97147 4301.44904 3163.64723 4302.24095 3164.26487 4303.0773 3164.82085 4303.95331 3165.31198 4304.86395 3165.73545 4305.80401 3166.08884 4306.76811 3166.37013 4307.75072 3166.57769 4308.54477 3166.6835 4308.7052 3166.7416 4308.82683 3166.86127 4308.88752 3167.02074 4308.87623 3167.19099 4308.795 3167.34105 4308.65864 3167.44361 4308.49193 3167.48 4081.4919 3167.48 Z M 4190.70384 3136.9889 L 4191.01965 3137.02 4239.28035 3137.02 4239.59616 3136.9889 4239.88094 3136.90251 4240.14339 3136.76222 4240.3887 3136.56091 4243.74517 3133.20444 4243.86219 3133.12327 4244.00024 3133.08825 4246.74455 3132.89727 4247.02247 3132.87075 4247.59165 3132.76217 4248.13657 3132.58511 4248.65501 3132.34116 4249.13878 3132.03415 4249.58025 3131.66893 4249.97247 3131.25125 4250.30925 3130.78771 4250.58528 3130.28562 4250.7962 3129.75289 4250.93869 3129.19793 4251.01051 3128.62948 4251.01051 3128.05652 4250.93869 3127.48807 4250.7962 3126.93311 4250.58528 3126.40038 4250.30925 3125.89829 4250.13258 3125.65511 4250.06327 3125.49495 4250.06875 3125.32052 4250.14798 3125.16503 4250.28587 3125.05807 4250.45619 3125.02 4254.20471 3125.02 4254.35778 3125.05045 4254.48755 3125.13716 4258.7543 3129.40391 4258.99961 3129.60522 4259.26206 3129.74551 4259.54684 3129.8319 4259.86265 3129.863 4298.1878 3129.863 4298.32794 3129.88835 4298.45031 3129.9612 4300.51293 3131.75534 4300.59416 3131.81321 4300.86122 3132.03415 4301.34499 3132.34116 4301.86343 3132.58511 4302.40835 3132.76217 4302.97117 3132.86953 4303.543 3132.90551 4304.11483 3132.86953 4304.67765 3132.76217 4305.22257 3132.58511 4305.74101 3132.34116 4306.22478 3132.03415 4306.66625 3131.66893 4307.05847 3131.25125 4307.39525 3130.78771 4307.67128 3130.28562 4307.8822 3129.75289 4308.02469 3129.19793 4308.09651 3128.62948 4308.09651 3128.05652 4308.02469 3127.48807 4307.8822 3126.93311 4307.67128 3126.40038 4307.39525 3125.89829 4307.05847 3125.43475 4306.66625 3125.01707 4306.22478 3124.65185 4305.74101 3124.34484 4305.22257 3124.10089 4304.67765 3123.92383 4304.11483 3123.81647 4303.543 3123.78049 4302.97117 3123.81647 4302.40835 3123.92383 4301.86343 3124.10089 4301.34499 3124.34484 4300.86122 3124.65185 4300.56605 3124.89406 4300.51293 3124.93069 4298.45036 3126.7248 4298.32798 3126.79765 4298.18784 3126.823 4260.63829 3126.823 4260.48522 3126.79255 4260.35545 3126.70584 4256.0887 3122.43909 4255.84339 3122.23778 4255.58094 3122.09749 4255.29616 3122.0111 4254.98035 3121.98 4250.34212 3121.98 4250.17181 3121.94193 4250.03391 3121.83497 4249.95469 3121.67948 4249.9492 3121.50505 4250.01851 3121.34489 4250.30925 3120.94471 4250.58528 3120.44262 4250.7962 3119.90989 4250.93869 3119.35493 4251.01051 3118.78648 4251.01051 3118.21352 4250.93869 3117.64507 4250.7962 3117.09011 4250.58528 3116.55738 4250.30925 3116.05529 4249.97247 3115.59175 4249.58025 3115.17407 4249.13878 3114.80885 4248.65501 3114.50184 4248.13657 3114.25789 4247.59165 3114.08083 4247.02069 3113.97191 4246.87529 3113.91283 4246.76381 3113.80235 4246.70342 3113.65748 4246.70342 3113.50052 4246.76381 3113.35565 4246.87529 3113.24517 4247.02069 3113.18609 4247.59165 3113.07717 4248.13657 3112.90011 4248.65501 3112.65616 4249.13878 3112.34915 4249.58025 3111.98393 4249.97247 3111.56625 4250.30925 3111.10271 4250.58528 3110.60062 4250.7962 3110.06789 4250.93869 3109.51293 4251.01051 3108.94448 4251.01051 3108.37152 4250.93869 3107.80307 4250.7962 3107.24811 4250.58528 3106.71538 4250.30925 3106.21329 4249.97247 3105.74975 4249.58025 3105.33207 4249.13878 3104.96685 4248.65501 3104.65984 4248.13657 3104.41589 4247.59165 3104.23883 4247.02883 3104.13147 4246.72725 3104.10251 4244.00023 3103.91274 4243.86218 3103.87772 4243.74515 3103.79655 4241.3877 3101.43909 4241.14239 3101.23778 4240.87994 3101.09749 4240.59516 3101.0111 4240.27935 3100.98 4200.01965 3100.98 4199.70384 3101.0111 4199.41906 3101.09749 4199.15661 3101.23778 4198.9113 3101.43909 4191.93909 3108.4113 4191.73778 3108.65661 4191.59749 3108.91906 4191.5111 3109.20384 4191.48 3109.51965 4191.48 3115.1446 4191.45465 3115.28474 4191.3818 3115.40712 4190.21987 3116.74292 4190.09815 3116.83757 4189.94966 3116.87915 4189.79648 3116.86147 4189.66137 3116.78716 4189.5644 3116.66727 4189.52 3116.51961 4189.4889 3116.20384 4189.40251 3115.91906 4189.26222 3115.65661 4189.06091 3115.4113 4186.0887 3112.43909 4185.84339 3112.23778 4185.58094 3112.09749 4185.29616 3112.0111 4184.98035 3111.98 4180.01965 3111.98 4179.70384 3112.0111 4179.41906 3112.09749 4179.15661 3112.23778 4178.9113 3112.43909 4175.71207 3115.63833 4175.59504 3115.7195 4175.457 3115.75452 4172.71882 3115.94507 4172.14531 3116.01824 4171.59011 3116.1608 4171.05738 3116.37172 4170.55529 3116.64775 4170.09175 3116.98453 4169.67407 3117.37675 4169.30885 3117.81822 4169.00184 3118.30199 4168.75789 3118.82043 4168.58083 3119.36535 4168.47347 3119.92817 4168.43749 3120.5 4168.47347 3121.07183 4168.58083 3121.63465 4168.75789 3122.17957 4169.00184 3122.69801 4169.30885 3123.18178 4169.67407 3123.62325 4170.09175 3124.01547 4170.55529 3124.35225 4171.05738 3124.62828 4171.59011 3124.8392 4172.14507 3124.98169 4172.71352 3125.05351 4173.28648 3125.05351 4173.85493 3124.98169 4174.40989 3124.8392 4174.94262 3124.62828 4175.44471 3124.35225 4175.90825 3124.01547 4176.32593 3123.62325 4176.69115 3123.18178 4176.99816 3122.69801 4177.24211 3122.17957 4177.41917 3121.63465 4177.52653 3121.07183 4177.55544 3120.77015 4177.74531 3118.04316 4177.78034 3117.90512 4177.8615 3117.7881 4180.51245 3115.13716 4180.64222 3115.05045 4180.79529 3115.02 4184.20471 3115.02 4184.35778 3115.05045 4184.48755 3115.13716 4184.86722 3115.51683 4184.95359 3115.64577 4184.98437 3115.79787 4184.95495 3115.95025 4184.86975 3116.07996 4184.74159 3116.16748 4184.58976 3116.19963 4184.40989 3116.1608 4183.85493 3116.01831 4183.28648 3115.94649 4182.71352 3115.94649 4182.14507 3116.01831 4181.59011 3116.1608 4181.05738 3116.37172 4180.55529 3116.64775 4180.09175 3116.98453 4179.67407 3117.37675 4179.30885 3117.81822 4179.00184 3118.30199 4178.75789 3118.82043 4178.58083 3119.36535 4178.47347 3119.92817 4178.43749 3120.5 4178.47347 3121.07183 4178.58083 3121.63465 4178.75789 3122.17957 4179.00184 3122.69801 4179.30885 3123.18178 4179.55212 3123.47823 4179.58768 3123.5298 4181.3818 3125.59239 4181.45465 3125.71477 4181.48 3125.85491 4181.48 3127.48035 4181.5111 3127.79616 4181.59749 3128.08094 4181.73778 3128.34339 4181.93909 3128.5887 4189.9113 3136.56091 4190.15661 3136.76222 4190.41906 3136.90251 4190.70384 3136.9889 Z M 4162.14507 3124.98169 L 4162.71352 3125.05351 4163.28648 3125.05351 4163.85493 3124.98169 4164.40989 3124.8392 4164.94262 3124.62828 4165.44471 3124.35225 4165.90825 3124.01547 4166.32593 3123.62325 4166.69115 3123.18178 4166.99816 3122.69801 4167.24211 3122.17957 4167.41917 3121.63465 4167.52653 3121.07183 4167.56251 3120.5 4167.52653 3119.92817 4167.41917 3119.36535 4167.24211 3118.82043 4166.99816 3118.30199 4166.69115 3117.81822 4166.32593 3117.37675 4165.90825 3116.98453 4165.44471 3116.64775 4164.94262 3116.37172 4164.40989 3116.1608 4163.85469 3116.01824 4163.28124 3115.94507 4160.54318 3115.7545 4160.40513 3115.71947 4160.28811 3115.6383 4147.7109 3103.06109 4147.46559 3102.85978 4147.20314 3102.71949 4146.91836 3102.6331 4146.60255 3102.602 4099.50435 3102.602 4099.36818 3102.57811 4099.24827 3102.50929 4097.56057 3101.10287 4097.4748 3101.04296 4097.28955 3100.88634 4096.83701 3100.59745 4096.35 3100.37145 4095.83721 3100.21238 4095.3078 3100.12308 4094.7712 3100.10514 4094.237 3100.15888 4093.71474 3100.28334 4093.21372 3100.47631 4092.74289 3100.73433 4092.31065 3101.0528 4091.92472 3101.42605 4091.59198 3101.8474 4091.31837 3102.30934 4091.10878 3102.80363 4090.96693 3103.32145 4090.89537 3103.85355 4090.89537 3104.39045 4090.96693 3104.92255 4091.10878 3105.44037 4091.31837 3105.93466 4091.59198 3106.3966 4091.92472 3106.81795 4092.31065 3107.1912 4092.74289 3107.50967 4093.21372 3107.76769 4093.71474 3107.96066 4094.237 3108.08512 4094.7712 3108.13886 4095.3078 3108.12092 4095.83721 3108.03162 4096.35 3107.87255 4096.83701 3107.64655 4097.28955 3107.35766 4097.56223 3107.13989 4099.24844 3105.73471 4099.36834 3105.66589 4099.50451 3105.642 4145.82691 3105.642 4145.97998 3105.67245 4146.10975 3105.75916 4158.13851 3117.78792 4158.21968 3117.90494 4158.2547 3118.04298 4158.44456 3120.7701 4158.47347 3121.07183 4158.58083 3121.63465 4158.75789 3122.17957 4159.00184 3122.69801 4159.30885 3123.18178 4159.67407 3123.62325 4160.09175 3124.01547 4160.55529 3124.35225 4161.05738 3124.62828 4161.59011 3124.8392 4162.14507 3124.98169 Z M 4152.14507 3124.98169 L 4152.71352 3125.05351 4153.28648 3125.05351 4153.85493 3124.98169 4154.40989 3124.8392 4154.94262 3124.62828 4155.44471 3124.35225 4155.90825 3124.01547 4156.32593 3123.62325 4156.69115 3123.18178 4156.99816 3122.69801 4157.24211 3122.17957 4157.41917 3121.63465 4157.52653 3121.07183 4157.56251 3120.5 4157.52653 3119.92817 4157.41917 3119.36535 4157.24211 3118.82043 4156.99816 3118.30199 4156.69115 3117.81822 4156.32593 3117.37675 4155.90825 3116.98453 4155.44471 3116.64775 4154.94262 3116.37172 4154.40989 3116.1608 4153.85469 3116.01824 4153.28117 3115.94507 4150.54322 3115.75453 4150.40517 3115.71951 4150.28815 3115.63834 4147.7109 3113.06109 4147.46559 3112.85978 4147.20314 3112.71949 4146.91836 3112.6331 4146.60255 3112.602 4099.50435 3112.602 4099.36818 3112.57811 4099.24827 3112.50929 4097.56057 3111.10287 4097.4748 3111.04296 4097.28955 3110.88634 4096.83701 3110.59745 4096.35 3110.37145 4095.83721 3110.21238 4095.3078 3110.12308 4094.7712 3110.10514 4094.237 3110.15888 4093.71474 3110.28334 4093.21372 3110.47631 4092.74289 3110.73433 4092.31065 3111.0528 4091.92472 3111.42605 4091.59198 3111.8474 4091.31837 3112.30934 4091.10878 3112.80363 4090.96693 3113.32145 4090.89537 3113.85355 4090.89537 3114.39045 4090.96693 3114.92255 4091.10878 3115.44037 4091.31837 3115.93466 4091.59198 3116.3966 4091.92472 3116.81795 4092.31065 3117.1912 4092.74289 3117.50967 4093.21372 3117.76769 4093.71474 3117.96066 4094.237 3118.08512 4094.7712 3118.13886 4095.3078 3118.12092 4095.83721 3118.03162 4096.35 3117.87255 4096.83701 3117.64655 4097.28955 3117.35766 4097.56223 3117.13989 4099.24844 3115.73471 4099.36834 3115.66589 4099.50451 3115.642 4129.06528 3115.642 4129.22131 3115.67369 4129.35262 3115.76373 4129.43841 3115.89786 4129.46507 3116.05482 4129.4284 3116.20975 4129.3342 3116.33811 4129.19739 3116.41955 4129.01524 3116.48329 4128.82232 3116.60451 4128.66121 3116.76562 4128.53999 3116.95854 4128.46474 3117.17359 4128.4367 3117.42246 4128.4367 3123.57754 4128.46474 3123.82641 4128.53999 3124.04146 4128.66121 3124.23438 4128.82232 3124.39549 4129.01524 3124.51671 4129.23029 3124.59196 4129.47916 3124.62 4136.52084 3124.62 4136.76971 3124.59196 4136.98476 3124.51671 4137.17768 3124.39549 4137.33879 3124.23438 4137.46001 3124.04146 4137.53526 3123.82641 4137.5633 3123.57754 4137.5633 3117.42246 4137.53526 3117.17359 4137.46001 3116.95854 4137.33879 3116.76562 4137.17768 3116.60451 4136.98476 3116.48329 4136.80261 3116.41955 4136.6658 3116.33811 4136.5716 3116.20975 4136.53493 3116.05482 4136.56159 3115.89786 4136.64738 3115.76373 4136.77869 3115.67369 4136.93472 3115.642 4140.82683 3115.642 4140.99715 3115.68007 4141.09744 3115.75787 4141.22528 3115.67245 4141.37835 3115.642 4144.62165 3115.642 4144.77472 3115.67245 4144.90256 3115.75787 4145.00285 3115.68007 4145.17317 3115.642 4145.82691 3115.642 4145.97998 3115.67245 4146.10975 3115.75916 4148.13848 3117.78789 4148.21965 3117.9049 4148.25467 3118.04294 4148.44456 3120.77016 4148.47347 3121.07183 4148.58083 3121.63465 4148.75789 3122.17957 4149.00184 3122.69801 4149.30885 3123.18178 4149.67407 3123.62325 4150.09175 3124.01547 4150.55529 3124.35225 4151.05738 3124.62828 4151.59011 3124.8392 4152.14507 3124.98169 Z M 4278.72868 3146.6853 L 4279.383 3146.64855 4280.01801 3146.54066 4280.63695 3146.36235 4281.23203 3146.11586 4281.79577 3145.80429 4282.32108 3145.43156 4282.80136 3145.00236 4283.23056 3144.52208 4283.60329 3143.99677 4283.91486 3143.43303 4284.16135 3142.83795 4284.33966 3142.21901 4284.44755 3141.584 4284.48367 3140.9409 4284.44755 3140.2978 4284.33966 3139.66279 4284.16135 3139.04385 4283.91486 3138.44877 4283.60329 3137.88503 4283.23056 3137.35972 4282.80136 3136.87944 4282.32108 3136.45024 4281.79577 3136.07751 4281.23203 3135.76594 4280.63695 3135.51945 4280.01801 3135.34114 4279.383 3135.23325 4278.72868 3135.1965 4273.23932 3135.1965 4272.585 3135.23325 4271.94999 3135.34114 4271.33105 3135.51945 4270.73597 3135.76594 4270.17223 3136.07751 4269.64692 3136.45024 4269.16664 3136.87944 4268.73744 3137.35972 4268.36471 3137.88503 4268.05314 3138.44877 4267.80665 3139.04385 4267.62834 3139.66279 4267.52045 3140.2978 4267.48433 3140.9409 4267.52045 3141.584 4267.62834 3142.21901 4267.80665 3142.83795 4268.05314 3143.43303 4268.36471 3143.99677 4268.73744 3144.52208 4269.16664 3145.00236 4269.64692 3145.43156 4270.17223 3145.80429 4270.73597 3146.11586 4271.33105 3146.36235 4271.94999 3146.54066 4272.585 3146.64855 4273.23932 3146.6853 4278.72868 3146.6853 Z M 4272.585 3101.76675 L 4273.23932 3101.8035 4278.72868 3101.8035 4279.383 3101.76675 4280.01801 3101.65886 4280.63695 3101.48055 4281.23203 3101.23406 4281.79577 3100.92249 4282.32108 3100.54976 4282.80136 3100.12056 4283.23056 3099.64028 4283.60329 3099.11497 4283.91486 3098.55123 4284.16135 3097.95615 4284.33966 3097.33721 4284.44755 3096.7022 4284.48367 3096.0591 4284.44755 3095.416 4284.33966 3094.78099 4284.16135 3094.16205 4283.91486 3093.56697 4283.60329 3093.00323 4283.23056 3092.47792 4282.80136 3091.99764 4282.32108 3091.56844 4281.79577 3091.19571 4281.23203 3090.88414 4280.63695 3090.63765 4280.01801 3090.45934 4279.383 3090.35145 4278.72868 3090.3147 4273.23932 3090.3147 4272.585 3090.35145 4271.94999 3090.45934 4271.33105 3090.63765 4270.73597 3090.88414 4270.17223 3091.19571 4269.64692 3091.56844 4269.16664 3091.99764 4268.73744 3092.47792 4268.36471 3093.00323 4268.05314 3093.56697 4267.80665 3094.16205 4267.62834 3094.78099 4267.52045 3095.416 4267.48433 3096.0591 4267.52045 3096.7022 4267.62834 3097.33721 4267.80665 3097.95615 4268.05314 3098.55123 4268.36471 3099.11497 4268.73744 3099.64028 4269.16664 3100.12056 4269.64692 3100.54976 4270.17223 3100.92249 4270.73597 3101.23406 4271.33105 3101.48055 4271.94999 3101.65886 4272.585 3101.76675 Z M 4303.543 3113.22051 L 4304.11483 3113.18453 4304.67765 3113.07717 4305.22257 3112.90011 4305.74101 3112.65616 4306.22478 3112.34915 4306.66625 3111.98393 4307.05847 3111.56625 4307.39525 3111.10271 4307.67128 3110.60062 4307.8822 3110.06789 4308.02469 3109.51293 4308.09651 3108.94448 4308.09651 3108.37152 4308.02469 3107.80307 4307.8822 3107.24811 4307.67128 3106.71538 4307.39525 3106.21329 4307.05847 3105.74975 4306.66625 3105.33207 4306.22478 3104.96685 4305.74101 3104.65984 4305.22257 3104.41589 4304.67765 3104.23883 4304.11483 3104.13147 4303.543 3104.09549 4302.97117 3104.13147 4302.40835 3104.23883 4301.86343 3104.41589 4301.34499 3104.65984 4300.86122 3104.96685 4300.41975 3105.33207 4300.02753 3105.74975 4299.69075 3106.21329 4299.41472 3106.71538 4299.2038 3107.24811 4299.06131 3107.80307 4298.98949 3108.37152 4298.98949 3108.94448 4299.06131 3109.51293 4299.2038 3110.06789 4299.41472 3110.60062 4299.69075 3111.10271 4300.02753 3111.56625 4300.41975 3111.98393 4300.86122 3112.34915 4301.34499 3112.65616 4301.86343 3112.90011 4302.40835 3113.07717 4302.97117 3113.18453 4303.543 3113.22051 Z M 4094.7712 3138.13886 L 4095.3078 3138.12092 4095.83721 3138.03162 4096.35 3137.87255 4096.83701 3137.64655 4097.28955 3137.35766 4097.69955 3137.01103 4098.05969 3136.61284 4098.36354 3136.1702 4098.60569 3135.69102 4098.7818 3135.18383 4098.88874 3134.65769 4098.9246 3134.122 4098.88874 3133.58631 4098.7818 3133.06017 4098.60569 3132.55298 4098.36354 3132.0738 4098.05969 3131.63116 4097.69955 3131.23297 4097.28955 3130.88634 4096.83701 3130.59745 4096.35 3130.37145 4095.83721 3130.21238 4095.3078 3130.12308 4094.7712 3130.10514 4094.237 3130.15888 4093.71474 3130.28334 4093.21372 3130.47631 4092.74289 3130.73433 4092.31065 3131.0528 4091.92472 3131.42605 4091.59198 3131.8474 4091.31837 3132.30934 4091.10878 3132.80363 4090.96693 3133.32145 4090.89537 3133.85355 4090.89537 3134.39045 4090.96693 3134.92255 4091.10878 3135.44037 4091.31837 3135.93466 4091.59198 3136.3966 4091.92472 3136.81795 4092.31065 3137.1912 4092.74289 3137.50967 4093.21372 3137.76769 4093.71474 3137.96066 4094.237 3138.08512 4094.7712 3138.13886 Z M 4140.97835 3118.47835 L 4140.97835 3116.41516 4140.55529 3116.64775 4140.09175 3116.98453 4139.67407 3117.37675 4139.30885 3117.81822 4139.00184 3118.30199 4138.91886 3118.47835 4140.97835 3118.47835 Z M 4140.97835 3124.58484 L 4140.97835 3122.52165 4138.91886 3122.52165 4139.00184 3122.69801 4139.30885 3123.18178 4139.67407 3123.62325 4140.09175 3124.01547 4140.55529 3124.35225 4140.97835 3124.58484 Z M 4147.08114 3118.47835 L 4146.99816 3118.30199 4146.69115 3117.81822 4146.32593 3117.37675 4145.90825 3116.98453 4145.44471 3116.64775 4145.02165 3116.41516 4145.02165 3118.47835 4147.08114 3118.47835 Z M 4145.02165 3122.52165 L 4145.02165 3124.58484 4145.44471 3124.35225 4145.90825 3124.01547 4146.32593 3123.62325 4146.69115 3123.18178 4146.99816 3122.69801 4147.08114 3122.52165 4145.02165 3122.52165 Z M 4093.1555 3122.372 L 4093.1555 3120.50821 4092.74289 3120.73433 4092.31065 3121.0528 4091.92472 3121.42605 4091.59198 3121.8474 4091.31837 3122.30934 4091.2918 3122.372 4093.1555 3122.372 Z M 4093.1555 3127.73579 L 4093.1555 3125.872 4091.2918 3125.872 4091.31837 3125.93466 4091.59198 3126.3966 4091.92472 3126.81795 4092.31065 3127.1912 4092.74289 3127.50967 4093.1555 3127.73579 Z M 4096.6555 3120.51322 L 4096.6555 3122.372 4098.51423 3122.372 4098.36354 3122.0738 4098.05969 3121.63116 4097.69955 3121.23297 4097.28955 3120.88634 4096.83701 3120.59745 4096.6555 3120.51322 Z M 4096.6555 3127.73078 L 4096.83701 3127.64655 4097.28955 3127.35766 4097.69955 3127.01103 4098.05969 3126.61284 4098.36354 3126.1702 4098.51423 3125.872 4096.6555 3125.872 4096.6555 3127.73078 Z "}],"B":[{"net":"GND","svgpath":"M 4081.4919 3167.48 L 4081.32323 3167.4427 4081.18602 3167.33776 4081.10586 3167.18475 4081.09769 3167.0122 4081.16304 3166.8523 4081.28972 3166.73486 4081.4541 3166.68179 4081.75279 3166.65344 4082.74255 3166.48321 4083.7166 3166.23861 4084.66936 3165.92105 4085.59538 3165.53233 4086.48934 3165.0747 4087.34614 3164.55077 4088.16085 3163.96354 4088.92883 3163.31638 4089.64565 3162.61299 4090.30723 3161.85741 4090.90977 3161.05395 4091.44982 3160.20722 4091.92429 3159.32207 4092.33046 3158.40358 4092.666 3157.457 4092.92898 3156.48775 4093.11792 3155.5014 4093.23171 3154.50357 4093.26971 3153.5 4093.23171 3152.49643 4093.11792 3151.4986 4092.92898 3150.51225 4092.666 3149.543 4092.33046 3148.59642 4091.92429 3147.67793 4091.44982 3146.79278 4090.90977 3145.94605 4090.30723 3145.14259 4089.64565 3144.38701 4088.92883 3143.68362 4088.16085 3143.03646 4087.34614 3142.44923 4086.48934 3141.9253 4085.59538 3141.46767 4084.66936 3141.07895 4083.7166 3140.76139 4082.74255 3140.51679 4081.75279 3140.34656 4080.75299 3140.25167 4079.74888 3140.23266 4078.74621 3140.28965 4077.75072 3140.42231 4076.76811 3140.62987 4075.80401 3140.91116 4074.86395 3141.26455 4073.95331 3141.68802 4073.0773 3142.17915 4072.24095 3142.73513 4071.44904 3143.35277 4070.7061 3144.02853 4070.01641 3144.75854 4069.38389 3145.53862 4068.81219 3146.36431 4068.30456 3147.23086 4067.86393 3148.13333 4067.49282 3149.06653 4067.19334 3150.02513 4066.96722 3151.00364 4066.81542 3151.99854 4066.7549 3152.15694 4066.63418 3152.27603 4066.47498 3152.33441 4066.30589 3152.32159 4066.15731 3152.23986 4066.05594 3152.10393 4066.02 3151.93821 4066.02 3085.06179 4066.05594 3084.89607 4066.15731 3084.76014 4066.30589 3084.67841 4066.47498 3084.66559 4066.63418 3084.72397 4066.7549 3084.84306 4066.81542 3085.00146 4066.96722 3085.99636 4067.19334 3086.97487 4067.49282 3087.93347 4067.86393 3088.86667 4068.30456 3089.76914 4068.81219 3090.63569 4069.38389 3091.46138 4070.01641 3092.24146 4070.7061 3092.97147 4071.44904 3093.64723 4072.24095 3094.26487 4073.0773 3094.82085 4073.95331 3095.31198 4074.86395 3095.73545 4075.80401 3096.08884 4076.76811 3096.37013 4077.75072 3096.57769 4078.74621 3096.71035 4079.74888 3096.76734 4080.75299 3096.74833 4081.75279 3096.65344 4082.74255 3096.48321 4083.7166 3096.23861 4084.66936 3095.92105 4085.59538 3095.53233 4086.48934 3095.0747 4087.34614 3094.55077 4088.16085 3093.96354 4088.92883 3093.31638 4089.64565 3092.61299 4090.30723 3091.85741 4090.90977 3091.05395 4091.44982 3090.20722 4091.92429 3089.32207 4092.33046 3088.40358 4092.666 3087.457 4092.92898 3086.48775 4093.11792 3085.5014 4093.23171 3084.50357 4093.26971 3083.5 4093.23171 3082.49643 4093.11792 3081.4986 4092.92898 3080.51225 4092.666 3079.543 4092.33046 3078.59642 4091.92429 3077.67793 4091.44982 3076.79278 4090.90977 3075.94605 4090.30723 3075.14259 4089.64565 3074.38701 4088.92883 3073.68362 4088.16085 3073.03646 4087.34614 3072.44923 4086.48934 3071.9253 4085.59538 3071.46767 4084.66936 3071.07895 4083.7166 3070.76139 4082.74255 3070.51679 4081.75279 3070.34656 4081.4541 3070.31821 4081.28972 3070.26514 4081.16304 3070.1477 4081.09769 3069.9878 4081.10586 3069.81525 4081.18602 3069.66224 4081.32323 3069.5573 4081.4919 3069.52 4308.49193 3069.52 4308.65864 3069.55639 4308.795 3069.65895 4308.87623 3069.80901 4308.88752 3069.97926 4308.82683 3070.13873 4308.7052 3070.2584 4308.54477 3070.3165 4307.75072 3070.42231 4306.76811 3070.62987 4305.80401 3070.91116 4304.86395 3071.26455 4303.95331 3071.68802 4303.0773 3072.17915 4302.24095 3072.73513 4301.44904 3073.35277 4300.7061 3074.02853 4300.01641 3074.75854 4299.38389 3075.53862 4298.81219 3076.36431 4298.30456 3077.23086 4297.86393 3078.13333 4297.49282 3079.06653 4297.19334 3080.02513 4296.96722 3081.00364 4296.81574 3081.99644 4296.73979 3082.99785 4296.73979 3084.00215 4296.81574 3085.00356 4296.96722 3085.99636 4297.19334 3086.97487 4297.49282 3087.93347 4297.86393 3088.86667 4298.30456 3089.76914 4298.81219 3090.63569 4299.38389 3091.46138 4300.01641 3092.24146 4300.7061 3092.97147 4301.44904 3093.64723 4302.24095 3094.26487 4303.0773 3094.82085 4303.95331 3095.31198 4304.86395 3095.73545 4305.80401 3096.08884 4306.76811 3096.37013 4307.75072 3096.57769 4308.74621 3096.71035 4309.74888 3096.76734 4310.75299 3096.74833 4311.75279 3096.65344 4312.74255 3096.48321 4313.7166 3096.23861 4314.66936 3095.92105 4315.59538 3095.53233 4316.48934 3095.0747 4317.34614 3094.55077 4318.16085 3093.96354 4318.92883 3093.31638 4319.64565 3092.61299 4320.30723 3091.85741 4320.90977 3091.05395 4321.44982 3090.20722 4321.92429 3089.32207 4322.33046 3088.40358 4322.666 3087.457 4322.92898 3086.48775 4323.11792 3085.5014 4323.18258 3084.93441 4323.23818 3084.77198 4323.35676 3084.64782 4323.51647 3084.58481 4323.68787 3084.59455 4323.83941 3084.67525 4323.94316 3084.81205 4323.98 3084.97973 4323.98 3152.02027 4323.94316 3152.18795 4323.83941 3152.32475 4323.68787 3152.40545 4323.51647 3152.41519 4323.35676 3152.35218 4323.23818 3152.22802 4323.18258 3152.06559 4323.11792 3151.4986 4322.92898 3150.51225 4322.666 3149.543 4322.33046 3148.59642 4321.92429 3147.67793 4321.44982 3146.79278 4320.90977 3145.94605 4320.30723 3145.14259 4319.64565 3144.38701 4318.92883 3143.68362 4318.16085 3143.03646 4317.34614 3142.44923 4316.48934 3141.9253 4315.59538 3141.46767 4314.66936 3141.07895 4313.7166 3140.76139 4312.74255 3140.51679 4311.75279 3140.34656 4310.75299 3140.25167 4309.74888 3140.23266 4308.74621 3140.28965 4307.75072 3140.42231 4306.76811 3140.62987 4305.80401 3140.91116 4304.86395 3141.26455 4303.95331 3141.68802 4303.0773 3142.17915 4302.24095 3142.73513 4301.44904 3143.35277 4300.7061 3144.02853 4300.01641 3144.75854 4299.38389 3145.53862 4298.81219 3146.36431 4298.30456 3147.23086 4297.86393 3148.13333 4297.49282 3149.06653 4297.19334 3150.02513 4296.96722 3151.00364 4296.81574 3151.99644 4296.73979 3152.99785 4296.73979 3154.00215 4296.81574 3155.00356 4296.96722 3155.99636 4297.19334 3156.97487 4297.49282 3157.93347 4297.86393 3158.86667 4298.30456 3159.76914 4298.81219 3160.63569 4299.38389 3161.46138 4300.01641 3162.24146 4300.7061 3162.97147 4301.44904 3163.64723 4302.24095 3164.26487 4303.0773 3164.82085 4303.95331 3165.31198 4304.86395 3165.73545 4305.80401 3166.08884 4306.76811 3166.37013 4307.75072 3166.57769 4308.54477 3166.6835 4308.7052 3166.7416 4308.82683 3166.86127 4308.88752 3167.02074 4308.87623 3167.19099 4308.795 3167.34105 4308.65864 3167.44361 4308.49193 3167.48 4081.4919 3167.48 Z M 4272.585 3146.64855 L 4273.23932 3146.6853 4278.72868 3146.6853 4279.383 3146.64855 4280.01801 3146.54066 4280.63695 3146.36235 4281.23203 3146.11586 4281.79577 3145.80429 4282.32108 3145.43156 4282.80136 3145.00236 4283.23056 3144.52208 4283.60329 3143.99677 4283.91486 3143.43303 4284.16135 3142.83795 4284.33966 3142.21901 4284.44755 3141.584 4284.48367 3140.9409 4284.44755 3140.2978 4284.33966 3139.66279 4284.16135 3139.04385 4283.91486 3138.44877 4283.60329 3137.88503 4283.23056 3137.35972 4282.80136 3136.87944 4282.32108 3136.45024 4281.79577 3136.07751 4281.23203 3135.76594 4280.63695 3135.51945 4280.01801 3135.34114 4279.383 3135.23325 4278.72868 3135.1965 4273.23932 3135.1965 4272.585 3135.23325 4271.94999 3135.34114 4271.33105 3135.51945 4270.73597 3135.76594 4270.17223 3136.07751 4269.64692 3136.45024 4269.16664 3136.87944 4268.73744 3137.35972 4268.36471 3137.88503 4268.05314 3138.44877 4267.80665 3139.04385 4267.62834 3139.66279 4267.52045 3140.2978 4267.48433 3140.9409 4267.52045 3141.584 4267.62834 3142.21901 4267.80665 3142.83795 4268.05314 3143.43303 4268.36471 3143.99677 4268.73744 3144.52208 4269.16664 3145.00236 4269.64692 3145.43156 4270.17223 3145.80429 4270.73597 3146.11586 4271.33105 3146.36235 4271.94999 3146.54066 4272.585 3146.64855 Z M 4272.585 3101.76675 L 4273.23932 3101.8035 4278.72868 3101.8035 4279.383 3101.76675 4280.01801 3101.65886 4280.63695 3101.48055 4281.23203 3101.23406 4281.79577 3100.92249 4282.32108 3100.54976 4282.80136 3100.12056 4283.23056 3099.64028 4283.60329 3099.11497 4283.91486 3098.55123 4284.16135 3097.95615 4284.33966 3097.33721 4284.44755 3096.7022 4284.48367 3096.0591 4284.44755 3095.416 4284.33966 3094.78099 4284.16135 3094.16205 4283.91486 3093.56697 4283.60329 3093.00323 4283.23056 3092.47792 4282.80136 3091.99764 4282.32108 3091.56844 4281.79577 3091.19571 4281.23203 3090.88414 4280.63695 3090.63765 4280.01801 3090.45934 4279.383 3090.35145 4278.72868 3090.3147 4273.23932 3090.3147 4272.585 3090.35145 4271.94999 3090.45934 4271.33105 3090.63765 4270.73597 3090.88414 4270.17223 3091.19571 4269.64692 3091.56844 4269.16664 3091.99764 4268.73744 3092.47792 4268.36471 3093.00323 4268.05314 3093.56697 4267.80665 3094.16205 4267.62834 3094.78099 4267.52045 3095.416 4267.48433 3096.0591 4267.52045 3096.7022 4267.62834 3097.33721 4267.80665 3097.95615 4268.05314 3098.55123 4268.36471 3099.11497 4268.73744 3099.64028 4269.16664 3100.12056 4269.64692 3100.54976 4270.17223 3100.92249 4270.73597 3101.23406 4271.33105 3101.48055 4271.94999 3101.65886 4272.585 3101.76675 Z M 4303.543 3132.90551 L 4304.11483 3132.86953 4304.67765 3132.76217 4305.22257 3132.58511 4305.74101 3132.34116 4306.22478 3132.03415 4306.66625 3131.66893 4307.05847 3131.25125 4307.39525 3130.78771 4307.67128 3130.28562 4307.8822 3129.75289 4308.02469 3129.19793 4308.09651 3128.62948 4308.09651 3128.05652 4308.02469 3127.48807 4307.8822 3126.93311 4307.67128 3126.40038 4307.39525 3125.89829 4307.05847 3125.43475 4306.66625 3125.01707 4306.22478 3124.65185 4305.74101 3124.34484 4305.22257 3124.10089 4304.67765 3123.92383 4304.11483 3123.81647 4303.543 3123.78049 4302.97117 3123.81647 4302.40835 3123.92383 4301.86343 3124.10089 4301.34499 3124.34484 4300.86122 3124.65185 4300.41975 3125.01707 4300.02753 3125.43475 4299.69075 3125.89829 4299.41472 3126.40038 4299.2038 3126.93311 4299.06131 3127.48807 4298.98949 3128.05652 4298.98949 3128.62948 4299.06131 3129.19793 4299.2038 3129.75289 4299.41472 3130.28562 4299.69075 3130.78771 4300.02753 3131.25125 4300.41975 3131.66893 4300.86122 3132.03415 4301.34499 3132.34116 4301.86343 3132.58511 4302.40835 3132.76217 4302.97117 3132.86953 4303.543 3132.90551 Z M 4163.28648 3125.05351 L 4163.85493 3124.98169 4164.40989 3124.8392 4164.94262 3124.62828 4165.44471 3124.35225 4165.90825 3124.01547 4166.32593 3123.62325 4166.69115 3123.18178 4166.99816 3122.69801 4167.24211 3122.17957 4167.41917 3121.63465 4167.52653 3121.07183 4167.56251 3120.5 4167.52653 3119.92817 4167.41917 3119.36535 4167.24211 3118.82043 4166.99816 3118.30199 4166.69115 3117.81822 4166.32593 3117.37675 4165.90825 3116.98453 4165.44471 3116.64775 4164.94262 3116.37172 4164.40989 3116.1608 4163.85493 3116.01831 4163.28648 3115.94649 4162.71352 3115.94649 4162.14507 3116.01831 4161.59011 3116.1608 4161.05738 3116.37172 4160.55529 3116.64775 4160.09175 3116.98453 4159.67407 3117.37675 4159.30885 3117.81822 4159.00184 3118.30199 4158.75789 3118.82043 4158.58083 3119.36535 4158.47347 3119.92817 4158.43749 3120.5 4158.47347 3121.07183 4158.58083 3121.63465 4158.75789 3122.17957 4159.00184 3122.69801 4159.30885 3123.18178 4159.67407 3123.62325 4160.09175 3124.01547 4160.55529 3124.35225 4161.05738 3124.62828 4161.59011 3124.8392 4162.14507 3124.98169 4162.71352 3125.05351 4163.28648 3125.05351 Z M 4173.28648 3125.05351 L 4173.85493 3124.98169 4174.40989 3124.8392 4174.94262 3124.62828 4175.44471 3124.35225 4175.90825 3124.01547 4176.32593 3123.62325 4176.69115 3123.18178 4176.99816 3122.69801 4177.24211 3122.17957 4177.41917 3121.63465 4177.52653 3121.07183 4177.56251 3120.5 4177.52653 3119.92817 4177.41917 3119.36535 4177.24211 3118.82043 4176.99816 3118.30199 4176.69115 3117.81822 4176.32593 3117.37675 4175.90825 3116.98453 4175.44471 3116.64775 4174.94262 3116.37172 4174.40989 3116.1608 4173.85493 3116.01831 4173.28648 3115.94649 4172.71352 3115.94649 4172.14507 3116.01831 4171.59011 3116.1608 4171.05738 3116.37172 4170.55529 3116.64775 4170.09175 3116.98453 4169.67407 3117.37675 4169.30885 3117.81822 4169.00184 3118.30199 4168.75789 3118.82043 4168.58083 3119.36535 4168.47347 3119.92817 4168.43749 3120.5 4168.47347 3121.07183 4168.58083 3121.63465 4168.75789 3122.17957 4169.00184 3122.69801 4169.30885 3123.18178 4169.67407 3123.62325 4170.09175 3124.01547 4170.55529 3124.35225 4171.05738 3124.62828 4171.59011 3124.8392 4172.14507 3124.98169 4172.71352 3125.05351 4173.28648 3125.05351 Z M 4152.14507 3124.98169 L 4152.71352 3125.05351 4153.28648 3125.05351 4153.85493 3124.98169 4154.40989 3124.8392 4154.94262 3124.62828 4155.44471 3124.35225 4155.90825 3124.01547 4156.32593 3123.62325 4156.69115 3123.18178 4156.99816 3122.69801 4157.24211 3122.17957 4157.41917 3121.63465 4157.52653 3121.07183 4157.56251 3120.5 4157.52653 3119.92817 4157.41917 3119.36535 4157.24211 3118.82043 4156.99816 3118.30199 4156.69115 3117.81822 4156.32593 3117.37675 4155.90825 3116.98453 4155.44471 3116.64775 4154.94262 3116.37172 4154.40989 3116.1608 4153.85493 3116.01831 4153.28648 3115.94649 4152.71352 3115.94649 4152.14507 3116.01831 4151.59011 3116.1608 4151.05738 3116.37172 4150.55529 3116.64775 4150.09175 3116.98453 4149.67407 3117.37675 4149.30885 3117.81822 4149.00184 3118.30199 4148.75789 3118.82043 4148.58083 3119.36535 4148.47347 3119.92817 4148.43749 3120.5 4148.47347 3121.07183 4148.58083 3121.63465 4148.75789 3122.17957 4149.00184 3122.69801 4149.30885 3123.18178 4149.67407 3123.62325 4150.09175 3124.01547 4150.55529 3124.35225 4151.05738 3124.62828 4151.59011 3124.8392 4152.14507 3124.98169 Z M 4192.14507 3124.98169 L 4192.71352 3125.05351 4193.28648 3125.05351 4193.85493 3124.98169 4194.40989 3124.8392 4194.94262 3124.62828 4195.44471 3124.35225 4195.90825 3124.01547 4196.32593 3123.62325 4196.69115 3123.18178 4196.99816 3122.69801 4197.24211 3122.17957 4197.41917 3121.63465 4197.52653 3121.07183 4197.56251 3120.5 4197.52653 3119.92817 4197.41917 3119.36535 4197.24211 3118.82043 4196.99816 3118.30199 4196.69115 3117.81822 4196.32593 3117.37675 4195.90825 3116.98453 4195.44471 3116.64775 4194.94262 3116.37172 4194.40989 3116.1608 4193.85493 3116.01831 4193.28648 3115.94649 4192.71352 3115.94649 4192.14507 3116.01831 4191.59011 3116.1608 4191.05738 3116.37172 4190.55529 3116.64775 4190.09175 3116.98453 4189.67407 3117.37675 4189.30885 3117.81822 4189.00184 3118.30199 4188.75789 3118.82043 4188.58083 3119.36535 4188.47347 3119.92817 4188.43749 3120.5 4188.47347 3121.07183 4188.58083 3121.63465 4188.75789 3122.17957 4189.00184 3122.69801 4189.30885 3123.18178 4189.67407 3123.62325 4190.09175 3124.01547 4190.55529 3124.35225 4191.05738 3124.62828 4191.59011 3124.8392 4192.14507 3124.98169 Z M 4142.14507 3124.98169 L 4142.71352 3125.05351 4143.28648 3125.05351 4143.85493 3124.98169 4144.40989 3124.8392 4144.94262 3124.62828 4145.44471 3124.35225 4145.90825 3124.01547 4146.32593 3123.62325 4146.69115 3123.18178 4146.99816 3122.69801 4147.24211 3122.17957 4147.41917 3121.63465 4147.52653 3121.07183 4147.56251 3120.5 4147.52653 3119.92817 4147.41917 3119.36535 4147.24211 3118.82043 4146.99816 3118.30199 4146.69115 3117.81822 4146.32593 3117.37675 4145.90825 3116.98453 4145.44471 3116.64775 4144.94262 3116.37172 4144.40989 3116.1608 4143.85493 3116.01831 4143.28648 3115.94649 4142.71352 3115.94649 4142.14507 3116.01831 4141.59011 3116.1608 4141.05738 3116.37172 4140.55529 3116.64775 4140.09175 3116.98453 4139.67407 3117.37675 4139.30885 3117.81822 4139.00184 3118.30199 4138.75789 3118.82043 4138.58083 3119.36535 4138.47347 3119.92817 4138.43749 3120.5 4138.47347 3121.07183 4138.58083 3121.63465 4138.75789 3122.17957 4139.00184 3122.69801 4139.30885 3123.18178 4139.67407 3123.62325 4140.09175 3124.01547 4140.55529 3124.35225 4141.05738 3124.62828 4141.59011 3124.8392 4142.14507 3124.98169 Z M 4182.14507 3124.98169 L 4182.71352 3125.05351 4183.28648 3125.05351 4183.85493 3124.98169 4184.40989 3124.8392 4184.94262 3124.62828 4185.44471 3124.35225 4185.90825 3124.01547 4186.32593 3123.62325 4186.69115 3123.18178 4186.99816 3122.69801 4187.24211 3122.17957 4187.41917 3121.63465 4187.52653 3121.07183 4187.56251 3120.5 4187.52653 3119.92817 4187.41917 3119.36535 4187.24211 3118.82043 4186.99816 3118.30199 4186.69115 3117.81822 4186.32593 3117.37675 4185.90825 3116.98453 4185.44471 3116.64775 4184.94262 3116.37172 4184.40989 3116.1608 4183.85493 3116.01831 4183.28648 3115.94649 4182.71352 3115.94649 4182.14507 3116.01831 4181.59011 3116.1608 4181.05738 3116.37172 4180.55529 3116.64775 4180.09175 3116.98453 4179.67407 3117.37675 4179.30885 3117.81822 4179.00184 3118.30199 4178.75789 3118.82043 4178.58083 3119.36535 4178.47347 3119.92817 4178.43749 3120.5 4178.47347 3121.07183 4178.58083 3121.63465 4178.75789 3122.17957 4179.00184 3122.69801 4179.30885 3123.18178 4179.67407 3123.62325 4180.09175 3124.01547 4180.55529 3124.35225 4181.05738 3124.62828 4181.59011 3124.8392 4182.14507 3124.98169 Z M 4246.457 3132.90551 L 4247.02883 3132.86953 4247.59165 3132.76217 4248.13657 3132.58511 4248.65501 3132.34116 4249.13878 3132.03415 4249.58025 3131.66893 4249.97247 3131.25125 4250.30925 3130.78771 4250.58528 3130.28562 4250.7962 3129.75289 4250.93869 3129.19793 4251.01051 3128.62948 4251.01051 3128.05652 4250.93869 3127.48807 4250.7962 3126.93311 4250.58528 3126.40038 4250.30925 3125.89829 4249.97247 3125.43475 4249.58025 3125.01707 4249.13878 3124.65185 4248.65501 3124.34484 4248.13657 3124.10089 4247.59165 3123.92383 4247.02883 3123.81647 4246.45756 3123.78053 4245.87176 3123.81903 4245.32235 3123.92383 4244.77743 3124.10089 4244.25899 3124.34484 4243.77522 3124.65185 4243.33375 3125.01707 4242.94153 3125.43475 4242.60475 3125.89829 4242.32872 3126.40038 4242.1178 3126.93311 4241.97531 3127.48807 4241.90349 3128.05652 4241.90349 3128.62948 4241.97531 3129.19793 4242.1178 3129.75289 4242.32872 3130.28562 4242.60475 3130.78771 4242.94153 3131.25125 4243.33375 3131.66893 4243.77522 3132.03415 4244.25899 3132.34116 4244.77743 3132.58511 4245.32235 3132.76217 4245.88517 3132.86953 4246.457 3132.90551 Z M 4246.45634 3113.22047 L 4247.04476 3113.18149 4247.59165 3113.07717 4248.13657 3112.90011 4248.65501 3112.65616 4249.13878 3112.34915 4249.58025 3111.98393 4249.97247 3111.56625 4250.30925 3111.10271 4250.58528 3110.60062 4250.7962 3110.06789 4250.93869 3109.51293 4251.01051 3108.94448 4251.01051 3108.37152 4250.93869 3107.80307 4250.7962 3107.24811 4250.58528 3106.71538 4250.30925 3106.21329 4249.97247 3105.74975 4249.58025 3105.33207 4249.13878 3104.96685 4248.65501 3104.65984 4248.13657 3104.41589 4247.59165 3104.23883 4247.02883 3104.13147 4246.457 3104.09549 4245.88517 3104.13147 4245.32235 3104.23883 4244.77743 3104.41589 4244.25899 3104.65984 4243.77522 3104.96685 4243.33375 3105.33207 4242.94153 3105.74975 4242.60475 3106.21329 4242.32872 3106.71538 4242.1178 3107.24811 4241.97531 3107.80307 4241.90349 3108.37152 4241.90349 3108.94448 4241.97531 3109.51293 4242.1178 3110.06789 4242.32872 3110.60062 4242.60475 3111.10271 4242.94153 3111.56625 4243.33375 3111.98393 4243.77522 3112.34915 4244.25899 3112.65616 4244.77743 3112.90011 4245.32235 3113.07717 4245.88517 3113.18453 4246.45634 3113.22047 Z M 4094.7712 3118.13886 L 4095.3078 3118.12092 4095.83721 3118.03162 4096.35 3117.87255 4096.83701 3117.64655 4097.28955 3117.35766 4097.69955 3117.01103 4098.05969 3116.61284 4098.36354 3116.1702 4098.60569 3115.69102 4098.7818 3115.18383 4098.88874 3114.65769 4098.9246 3114.122 4098.88874 3113.58631 4098.7818 3113.06017 4098.60569 3112.55298 4098.36354 3112.0738 4098.05969 3111.63116 4097.69955 3111.23297 4097.28955 3110.88634 4096.83701 3110.59745 4096.35 3110.37145 4095.83721 3110.21238 4095.3078 3110.12308 4094.7712 3110.10514 4094.237 3110.15888 4093.71474 3110.28334 4093.21372 3110.47631 4092.74289 3110.73433 4092.31065 3111.0528 4091.92472 3111.42605 4091.59198 3111.8474 4091.31837 3112.30934 4091.10878 3112.80363 4090.96693 3113.32145 4090.89537 3113.85355 4090.89537 3114.39045 4090.96693 3114.92255 4091.10878 3115.44037 4091.31837 3115.93466 4091.59198 3116.3966 4091.92472 3116.81795 4092.31065 3117.1912 4092.74289 3117.50967 4093.21372 3117.76769 4093.71474 3117.96066 4094.237 3118.08512 4094.7712 3118.13886 Z M 4094.7712 3128.13886 L 4095.3078 3128.12092 4095.83721 3128.03162 4096.35 3127.87255 4096.83701 3127.64655 4097.28955 3127.35766 4097.69955 3127.01103 4098.05969 3126.61284 4098.36354 3126.1702 4098.60569 3125.69102 4098.7818 3125.18383 4098.88874 3124.65769 4098.9246 3124.122 4098.88874 3123.58631 4098.7818 3123.06017 4098.60569 3122.55298 4098.36354 3122.0738 4098.05969 3121.63116 4097.69955 3121.23297 4097.28955 3120.88634 4096.83701 3120.59745 4096.35 3120.37145 4095.83721 3120.21238 4095.3078 3120.12308 4094.7712 3120.10514 4094.237 3120.15888 4093.71474 3120.28334 4093.21372 3120.47631 4092.74289 3120.73433 4092.31065 3121.0528 4091.92472 3121.42605 4091.59198 3121.8474 4091.31837 3122.30934 4091.10878 3122.80363 4090.96693 3123.32145 4090.89537 3123.85355 4090.89537 3124.39045 4090.96693 3124.92255 4091.10878 3125.44037 4091.31837 3125.93466 4091.59198 3126.3966 4091.92472 3126.81795 4092.31065 3127.1912 4092.74289 3127.50967 4093.21372 3127.76769 4093.71474 3127.96066 4094.237 3128.08512 4094.7712 3128.13886 Z M 4094.7712 3108.13886 L 4095.3078 3108.12092 4095.83721 3108.03162 4096.35 3107.87255 4096.83701 3107.64655 4097.28955 3107.35766 4097.69955 3107.01103 4098.05969 3106.61284 4098.36354 3106.1702 4098.60569 3105.69102 4098.7818 3105.18383 4098.88874 3104.65769 4098.9246 3104.122 4098.88874 3103.58631 4098.7818 3103.06017 4098.60569 3102.55298 4098.36354 3102.0738 4098.05969 3101.63116 4097.69955 3101.23297 4097.28955 3100.88634 4096.83701 3100.59745 4096.35 3100.37145 4095.83721 3100.21238 4095.3078 3100.12308 4094.7712 3100.10514 4094.237 3100.15888 4093.71474 3100.28334 4093.21372 3100.47631 4092.74289 3100.73433 4092.31065 3101.0528 4091.92472 3101.42605 4091.59198 3101.8474 4091.31837 3102.30934 4091.10878 3102.80363 4090.96693 3103.32145 4090.89537 3103.85355 4090.89537 3104.39045 4090.96693 3104.92255 4091.10878 3105.44037 4091.31837 3105.93466 4091.59198 3106.3966 4091.92472 3106.81795 4092.31065 3107.1912 4092.74289 3107.50967 4093.21372 3107.76769 4093.71474 3107.96066 4094.237 3108.08512 4094.7712 3108.13886 Z M 4130.97835 3118.7 L 4130.97835 3116.38 4129.47916 3116.38 4129.23029 3116.40804 4129.01524 3116.48329 4128.82232 3116.60451 4128.66121 3116.76562 4128.53999 3116.95854 4128.46474 3117.17359 4128.4367 3117.42246 4128.4367 3118.7 4130.97835 3118.7 Z M 4130.97835 3124.62 L 4130.97835 3122.3 4128.4367 3122.3 4128.4367 3123.57754 4128.46474 3123.82641 4128.53999 3124.04146 4128.66121 3124.23438 4128.82232 3124.39549 4129.01524 3124.51671 4129.23029 3124.59196 4129.47916 3124.62 4130.97835 3124.62 Z M 4135.02165 3122.3 L 4135.02165 3124.62 4136.52084 3124.62 4136.76971 3124.59196 4136.98476 3124.51671 4137.17768 3124.39549 4137.33879 3124.23438 4137.46001 3124.04146 4137.53526 3123.82641 4137.5633 3123.57754 4137.5633 3122.3 4135.02165 3122.3 Z M 4137.5633 3118.7 L 4137.5633 3117.42246 4137.53526 3117.17359 4137.46001 3116.95854 4137.33879 3116.76562 4137.17768 3116.60451 4136.98476 3116.48329 4136.76971 3116.40804 4136.52084 3116.38 4135.02165 3116.38 4135.02165 3118.7 4137.5633 3118.7 Z M 4301.52135 3106.63635 L 4301.52135 3104.57686 4301.34499 3104.65984 4300.86122 3104.96685 4300.41975 3105.33207 4300.02753 3105.74975 4299.69075 3106.21329 4299.45816 3106.63635 4301.52135 3106.63635 Z M 4301.52135 3112.73914 L 4301.52135 3110.67965 4299.45816 3110.67965 4299.69075 3111.10271 4300.02753 3111.56625 4300.41975 3111.98393 4300.86122 3112.34915 4301.34499 3112.65616 4301.52135 3112.73914 Z M 4248.47865 3120.52165 L 4248.47865 3122.58114 4248.65501 3122.49816 4249.13878 3122.19115 4249.58025 3121.82593 4249.97247 3121.40825 4250.30925 3120.94471 4250.54184 3120.52165 4248.47865 3120.52165 Z M 4244.43535 3122.58114 L 4244.43535 3120.52165 4242.37216 3120.52165 4242.60475 3120.94471 4242.94153 3121.40825 4243.33375 3121.82593 4243.77522 3122.19115 4244.25899 3122.49816 4244.43535 3122.58114 Z M 4242.60475 3116.05529 L 4242.37216 3116.47835 4244.43535 3116.47835 4244.43535 3114.41886 4244.25899 3114.50184 4243.77522 3114.80885 4243.33375 3115.17407 4242.94153 3115.59175 4242.60475 3116.05529 Z M 4248.47865 3114.41886 L 4248.47865 3116.47835 4250.54184 3116.47835 4250.30925 3116.05529 4249.97247 3115.59175 4249.58025 3115.17407 4249.13878 3114.80885 4248.65501 3114.50184 4248.47865 3114.41886 Z M 4305.56465 3110.67965 L 4305.56465 3112.73914 4305.74101 3112.65616 4306.22478 3112.34915 4306.66625 3111.98393 4307.05847 3111.56625 4307.39525 3111.10271 4307.62784 3110.67965 4305.56465 3110.67965 Z M 4305.56465 3104.57686 L 4305.56465 3106.63635 4307.62784 3106.63635 4307.39525 3106.21329 4307.05847 3105.74975 4306.66625 3105.33207 4306.22478 3104.96685 4305.74101 3104.65984 4305.56465 3104.57686 Z M 4093.1555 3132.372 L 4093.1555 3130.50821 4092.74289 3130.73433 4092.31065 3131.0528 4091.92472 3131.42605 4091.59198 3131.8474 4091.31837 3132.30934 4091.2918 3132.372 4093.1555 3132.372 Z M 4093.1555 3137.73579 L 4093.1555 3135.872 4091.2918 3135.872 4091.31837 3135.93466 4091.59198 3136.3966 4091.92472 3136.81795 4092.31065 3137.1912 4092.74289 3137.50967 4093.1555 3137.73579 Z M 4096.6555 3130.51322 L 4096.6555 3132.372 4098.51423 3132.372 4098.36354 3132.0738 4098.05969 3131.63116 4097.69955 3131.23297 4097.28955 3130.88634 4096.83701 3130.59745 4096.6555 3130.51322 Z M 4096.6555 3135.872 L 4096.6555 3137.73078 4096.83701 3137.64655 4097.28955 3137.35766 4097.69955 3137.01103 4098.05969 3136.61284 4098.36354 3136.1702 4098.51423 3135.872 4096.6555 3135.872 Z "}]},"pads":[],"nets":["GND","3.3V","SCL","SDA","SWA","SWB","SW"],"bom":{"both":[[1,"XH2.54-7P 直插","CONN-TH_XH2.54-7P",[["CN2",0]],[" ","XH2.54-7P 直插","LCSC","C9900000729"]],[3,"0.1uF","CAP 0603",[["C3",1],["C8",2],["C9",3]],["KEMET","C0603C104K3RACAUTO","LCSC","C172738"]],[1,"EC11","SW-TH_5P-L11.8-W12.0-P2.50-LS14.5",[["SW1",4]],["BOURNS","PEC11L-4115F-S0020","LCSC","C143799"]],[1,"0.91OLED-IIC-IO4","0.91-OLED-IIC-12832",[["U6",5]],[" "," "," "," "]]],"F":[[3,"0.1uF","CAP 0603",[["C3",1],["C8",2],["C9",3]],["KEMET","C0603C104K3RACAUTO","LCSC","C172738"]],[1,"EC11","SW-TH_5P-L11.8-W12.0-P2.50-LS14.5",[["SW1",4]],["BOURNS","PEC11L-4115F-S0020","LCSC","C143799"]],[1,"0.91OLED-IIC-IO4","0.91-OLED-IIC-12832",[["U6",5]],[" "," "," "," "]]],"B":[[1,"XH2.54-7P 直插","CONN-TH_XH2.54-7P",[["CN2",0]],[" ","XH2.54-7P 直插","LCSC","C9900000729"]]],"skipped":[],"customColumns":["BOM_Manufacturer","BOM_Manufacturer Part","BOM_Supplier","BOM_Supplier Part"]}};
///////////////////////////////////////////////

///////////////////////////////////////////////
/* Utility functions */

var storagePrefix = 'ibom__' + pcbdata.metadata.title + '__' +
  pcbdata.metadata.revision + '__#';

function buildKeyForLocalStorageDict() {  
  return storagePrefix;
}

var storage;
var _isLocalStorageUsed = false;

function initStorage(key) {
  try {
    window.localStorage.getItem("blank");
    storage = window.localStorage;    
    _isLocalStorageUsed = true;
  } catch (e) {
    // localStorage not available
  }
  if (!storage) {
    try {
      window.sessionStorage.getItem("blank");
      storage = window.sessionStorage;      
    } catch (e) {
      // sessionStorage also not available
    }
  }
}



function readStorage(key) {
  if(!storage) {
    return null;
  }

  if(!_isLocalStorageUsed) {    
    return storage.getItem(storagePrefix + key);
  }

  try {
    var dictKey = buildKeyForLocalStorageDict();
    var obj = JSON.parse(storage.getItem(dictKey));    
    if(!obj || !obj.hasOwnProperty(key)) {
      return null;
    }

    return JSON.parse(storage.getItem(dictKey))[key];
  } catch(e) {
    console.log('[ibom]: Unable to obtain a value from local storage!');
    console.log(e);
  }
  
  // Original implementation
  // return storage.getItem(storagePrefix + key);
}


function writeStorage(key, value) {
  if(!storage) {
    return;
  }

  if(!_isLocalStorageUsed) {
    storage.setItem(storagePrefix + key, value);
    return;
  }

  try {
    var dictKey = buildKeyForLocalStorageDict();
    if(!storage.getItem(dictKey)) {
      storage.setItem(dictKey,JSON.stringify({
        _storagePrefix: storagePrefix
      }));
    }

    var obj = JSON.parse(storage.getItem(dictKey));
    obj[key] = value;
    storage.setItem(dictKey,JSON.stringify(obj));            
  } catch(e) {
    console.log('[ibom]: Unable to write key to local storage!');
    console.log(e);
  }
  
  // Original implementation
  // storage.setItem(storagePrefix + key, value);
}

function fancyDblClickHandler(el, onsingle, ondouble) {
  return function() {
    if (el.getAttribute("data-dblclick") == null) {
      el.setAttribute("data-dblclick", 1);
      setTimeout(function() {
        if (el.getAttribute("data-dblclick") == 1) {
          onsingle();
        }
        el.removeAttribute("data-dblclick");
      }, 200);
    } else {
      el.removeAttribute("data-dblclick");
      ondouble();
    }
  }
}

function smoothScrollToRow(rowid) {
  document.getElementById(rowid).scrollIntoView({
    behavior: "smooth",
    block: "center",
    inline: "nearest"
  });
}

function focusInputField(input) {
  input.scrollIntoView(false);
  input.focus();
  input.select();
}

function copyToClipboard() {
  var text = '';
  for (var node of bomhead.childNodes[0].childNodes) {
    if (node.firstChild) {
      text = text + node.firstChild.nodeValue;
    }
    if (node != bomhead.childNodes[0].lastChild) {
      text += '\t';
    }
  }
  text += '\n';
  for (var row of bombody.childNodes) {
    for (var cell of row.childNodes) {
      for (var node of cell.childNodes) {
        if (node.nodeName == "INPUT") {
          if (node.checked) {
            text = text + '✓';
          }
        } else if (node.nodeName == "MARK") {
          text = text + node.firstChild.nodeValue;
        } else {
          text = text + node.nodeValue;
        }
      }
      if (cell != row.lastChild) {
        text += '\t';
      }
    }
    text += '\n';
  }
  var textArea = document.createElement("textarea");
  textArea.classList.add('clipboard-temp');
  textArea.value = text;

  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    if (document.execCommand('copy')) {
      console.log('Bom copied to clipboard.');
    }
  } catch (err) {
    console.log('Can not copy to clipboard.');
  }

  document.body.removeChild(textArea);
}

function removeGutterNode(node) {
  for (var i = 0; i < node.childNodes.length; i++) {
    if (node.childNodes[i].classList &&
      node.childNodes[i].classList.contains("gutter")) {
      node.removeChild(node.childNodes[i]);
      break;
    }
  }
}

function cleanGutters() {
  removeGutterNode(document.getElementById("bot"));
  removeGutterNode(document.getElementById("canvasdiv"));
}

var units = {
  prefixes: {
    giga: ["G", "g", "giga", "Giga", "GIGA"],
    mega: ["M", "mega", "Mega", "MEGA"],
    kilo: ["K", "k", "kilo", "Kilo", "KILO"],
    milli: ["m", "milli", "Milli", "MILLI"],
    micro: ["U", "u", "micro", "Micro", "MICRO", "μ", "µ"], // different utf8 μ
    nano: ["N", "n", "nano", "Nano", "NANO"],
    pico: ["P", "p", "pico", "Pico", "PICO"],
  },
  unitsShort: ["R", "r", "Ω", "F", "f", "H", "h"],
  unitsLong: [
    "OHM", "Ohm", "ohm", "ohms",
    "FARAD", "Farad", "farad",
    "HENRY", "Henry", "henry"
  ],
  getMultiplier: function(s) {
    if (this.prefixes.giga.includes(s)) return 1e9;
    if (this.prefixes.mega.includes(s)) return 1e6;
    if (this.prefixes.kilo.includes(s)) return 1e3;
    if (this.prefixes.milli.includes(s)) return 1e-3;
    if (this.prefixes.micro.includes(s)) return 1e-6;
    if (this.prefixes.nano.includes(s)) return 1e-9;
    if (this.prefixes.pico.includes(s)) return 1e-12;
    return 1;
  },
  valueRegex: null,
}

function initUtils() {
  var allPrefixes = units.prefixes.giga
                    .concat(units.prefixes.mega)
                    .concat(units.prefixes.kilo)
                    .concat(units.prefixes.milli)
                    .concat(units.prefixes.micro)
                    .concat(units.prefixes.nano)
                    .concat(units.prefixes.pico);
  var allUnits = units.unitsShort.concat(units.unitsLong);
  units.valueRegex = new RegExp("^([0-9\.]+)" +
                         "\\s*(" + allPrefixes.join("|") + ")?" +
                         "(" + allUnits.join("|") + ")?" +
                         "(\\b.*)?$", "");
  units.valueAltRegex = new RegExp("^([0-9]*)" +
                         "(" + units.unitsShort.join("|") + ")?" +
                         "([GgMmKkUuNnPp])?" +
                         "([0-9]*)" +
                         "(\\b.*)?$", "");
  for (var bom_type of ["both", "F", "B"]) {
    for (var row of pcbdata.bom[bom_type]) {
      row.push(parseValue(row[1], row[3][0][0]));
    }
  }
}

function parseValue(val, ref) {
  var inferUnit = (unit, ref) => {
    if (unit) {
      unit = unit.toLowerCase();
      if (unit == 'Ω' || unit == "ohm" || unit == "ohms") {
        unit = 'r';
      }
      unit = unit[0];
    } else {
      ref = /^([a-z]+)\d+$/i.exec(ref);
      if (ref) {
        ref = ref[1].toLowerCase();
        if (ref == "c") unit = 'f';
        else if (ref == "l") unit = 'h';
        else if (ref == "r" || ref == "rv") unit = 'r';
        else unit = null;
      }
    }
    return unit;
  };
  val = val.replace(/,/g, "");
  var match = units.valueRegex.exec(val);
  var unit;
  if (match) {
    val = parseFloat(match[1]);
    if (match[2]) {
      val = val * units.getMultiplier(match[2]);
    }
    unit = inferUnit(match[3], ref);
    if (!unit) return null;
    else return {
      val: val,
      unit: unit,
      extra: match[4],
    }
  }
  match = units.valueAltRegex.exec(val);
  if (match && (match[1] || match[4])) {
    val = parseFloat(match[1] + "." + match[4]);
    if (match[3]) {
      val = val * units.getMultiplier(match[3]);
    }
    unit = inferUnit(match[2], ref);
    if (!unit) return null;
    else return {
      val: val,
      unit: unit,
      extra: match[5],
    }
  }
  return null;
}

function valueCompare(a, b, stra, strb) {
  if (a === null && b === null) {
    // Failed to parse both values, compare them as strings.
    if (stra != strb) return stra > strb ? 1 : -1;
    else return 0;
  } else if (a === null) {
    return 1;
  } else if (b === null) {
    return -1;
  } else {
    if (a.unit != b.unit) return a.unit > b.unit ? 1 : -1;
    else if (a.val != b.val) return a.val > b.val ? 1 : -1;
    else if (a.extra != b.extra) return a.extra > b.extra ? 1 : -1;
    else return 0;
  }
}

function validateSaveImgDimension(element) {
  var valid = false;
  var intValue = 0;
  if (/^[1-9]\d*$/.test(element.value)) {
    intValue = parseInt(element.value);
    if (intValue <= 16000) {
      valid = true;
    }
  }
  if (valid) {
    element.classList.remove("invalid");
  } else {
    element.classList.add("invalid");
  }
  return intValue;
}

function saveImage(layer) {
  var width = validateSaveImgDimension(document.getElementById("render-save-width"));
  var height = validateSaveImgDimension(document.getElementById("render-save-height"));
  var bgcolor = null;
  if (!document.getElementById("render-save-transparent").checked) {
    var style = getComputedStyle(topmostdiv);
    bgcolor = style.getPropertyValue("background-color");
  }
  if (!width || !height) return;

  // Prepare image
  var canvas = document.createElement("canvas");
  var layerdict = {
    transform: {
      x: 0,
      y: 0,
      s: 1,
      panx: 0,
      pany: 0,
      zoom: 1,
    },
    bg: canvas,
    fab: canvas,
    silk: canvas,
    highlight: canvas,
    layer: layer,
  }
  // Do the rendering
  recalcLayerScale(layerdict, width, height);
  prepareLayer(layerdict);
  clearCanvas(canvas, bgcolor);
  drawBackground(layerdict, false);
  drawHighlightsOnLayer(layerdict, false);

  // Save image
  var imgdata = canvas.toDataURL("image/png");

  var filename = pcbdata.metadata.title;
  if (pcbdata.metadata.revision) {
    filename += `.${pcbdata.metadata.revision}`;
  }
  filename += `.${layer}.png`;
  saveFile(filename, dataURLtoBlob(imgdata));
}

function saveSettings() {
  var data = {
    type: "InteractiveHtmlBom settings",
    version: 1,
    pcbmetadata: pcbdata.metadata,
    settings: settings,
  }
  var blob = new Blob([JSON.stringify(data, null, 4)], {type: "application/json"});
  saveFile(`${pcbdata.metadata.title}.settings.json`, blob);
}

function loadSettings() {
  var input = document.createElement("input");
  input.type = "file";
  input.accept = ".settings.json";
  input.onchange = function(e) {
    var file = e.target.files[0];
    var reader = new FileReader();
    reader.onload = readerEvent => {
      var content = readerEvent.target.result;
      var newSettings;
      try {
        newSettings = JSON.parse(content);
      } catch(e) {
        alert("Selected file is not InteractiveHtmlBom settings file.");
        return;
      }
      if (newSettings.type != "InteractiveHtmlBom settings") {
        alert("Selected file is not InteractiveHtmlBom settings file.");
        return;
      }
      var metadataMatches = newSettings.hasOwnProperty("pcbmetadata");
      if (metadataMatches) {
        for (var k in pcbdata.metadata) {
          if (!newSettings.pcbmetadata.hasOwnProperty(k) || newSettings.pcbmetadata[k] != pcbdata.metadata[k]) {
            metadataMatches = false;
          }
        }
      }
      if (!metadataMatches) {
        var currentMetadata = JSON.stringify(pcbdata.metadata, null, 4);
        var fileMetadata = JSON.stringify(newSettings.pcbmetadata, null, 4);
        if (!confirm(
          `Settins file metadata does not match current metadata.\n\n` +
          `Page metadata:\n${currentMetadata}\n\n` +
          `Settings file metadata:\n${fileMetadata}\n\n` +
          `Press OK if you would like to import settings anyway.`)) {
          return;
        }
      }
      overwriteSettings(newSettings.settings);
    }
    reader.readAsText(file, 'UTF-8');
  }
  input.click();
}

function overwriteSettings(newSettings) {

  initDone = false;
  Object.assign(settings, newSettings);
  writeStorage("bomlayout", settings.bomlayout);
  writeStorage("bommode", settings.bommode);
  writeStorage("canvaslayout", settings.canvaslayout);
  writeStorage("bomCheckboxes", settings.checkboxes.join(","));
  document.getElementById("bomCheckboxes").value = settings.checkboxes.join(",");
  for (var checkbox of settings.checkboxes) {
    writeStorage("checkbox_" + checkbox, settings.checkboxStoredRefs[checkbox]);
  }
  writeStorage("darkenWhenChecked", settings.darkenWhenChecked);
  padsVisible(settings.renderPads);
  document.getElementById("padsCheckbox").checked = settings.renderPads;
  fabricationVisible(settings.renderFabrication);
  document.getElementById("fabricationCheckbox").checked = settings.renderFabrication;
  silkscreenVisible(settings.renderSilkscreen);
  document.getElementById("silkscreenCheckbox").checked = settings.renderSilkscreen;
  referencesVisible(settings.renderReferences);
  document.getElementById("referencesCheckbox").checked = settings.renderReferences;
  valuesVisible(settings.renderValues);
  document.getElementById("valuesCheckbox").checked = settings.renderValues;
  tracksVisible(settings.renderTracks);
  document.getElementById("tracksCheckbox").checked = settings.renderTracks;
  zonesVisible(settings.renderZones);
  document.getElementById("zonesCheckbox").checked = settings.renderZones;
  dnpOutline(settings.renderDnpOutline);
  document.getElementById("dnpOutlineCheckbox").checked = settings.renderDnpOutline;
  setRedrawOnDrag(settings.redrawOnDrag);
  document.getElementById("dragCheckbox").checked = settings.redrawOnDrag;
  setShowCrosshair(settings.showCrosshair);
  document.getElementById("crosshairCheckbox").checked = settings.showCrosshair;
  setDarkMode(settings.darkMode);
  document.getElementById("darkmodeCheckbox").checked = settings.darkMode;
  setHighlightPin1(settings.highlightpin1);
  document.getElementById("highlightpin1Checkbox").checked = settings.highlightpin1;
  writeStorage("boardRotation", settings.boardRotation);
  document.getElementById("boardRotation").value = settings.boardRotation / 5;
  document.getElementById("rotationDegree").textContent = settings.boardRotation;
  initDone = true;
  prepCheckboxes();
  changeBomLayout(settings.bomlayout);
}

function saveFile(filename, blob) {
  var link = document.createElement("a");
  var objurl = URL.createObjectURL(blob);
  link.download = filename;
  link.href = objurl;
  link.click();
}

function dataURLtoBlob(dataurl) {
  var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
      bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
  while(n--){
      u8arr[n] = bstr.charCodeAt(n);
  }
  return new Blob([u8arr], {type:mime});
}

var settings = {
  canvaslayout: "default",
  bomlayout: "default",
  bommode: "grouped",
  checkboxes: [],
  checkboxStoredRefs: {},
  darkMode: false,
  highlightpin1: false,
  redrawOnDrag: true,
  boardRotation: 0,
  renderPads: true,
  renderReferences: true,
  renderValues: true,
  renderSilkscreen: true,
  renderFabrication: true,
  renderDnpOutline: false,
  renderTracks: true,
  renderZones: true,
}

function initDefaults() {
  settings.bomlayout = readStorage("bomlayout");
  if (settings.bomlayout === null) {
    settings.bomlayout = config.bom_view;
  }
  if (!['bom-only', 'left-right', 'top-bottom'].includes(settings.bomlayout)) {
    settings.bomlayout = config.bom_view;
  }
  settings.bommode = readStorage("bommode");
  if (settings.bommode === null) {
    settings.bommode = "grouped";
  }
  if (!["grouped", "ungrouped", "netlist"].includes(settings.bommode)) {
    settings.bommode = "grouped";
  }
  settings.canvaslayout = readStorage("canvaslayout");
  if (settings.canvaslayout === null) {
    settings.canvaslayout = config.layer_view;
  }
  var bomCheckboxes = readStorage("bomCheckboxes");
  if (bomCheckboxes === null) {
    bomCheckboxes = config.checkboxes;
  }
  settings.checkboxes = bomCheckboxes.split(",").filter((e) => e);
  document.getElementById("bomCheckboxes").value = bomCheckboxes;

  settings.darkenWhenChecked = readStorage("darkenWhenChecked") || "";
  populateDarkenWhenCheckedOptions();

  function initBooleanSetting(storageString, def, elementId, func) {    
    var b = readStorage(storageString);
    if (b === null) {
      b = def;
    } else {
      b = (b === true);
    }
    document.getElementById(elementId).checked = b;
    func(b);
  }

  initBooleanSetting("padsVisible", config.show_pads, "padsCheckbox", padsVisible);
  initBooleanSetting("fabricationVisible", config.show_fabrication, "fabricationCheckbox", fabricationVisible);
  initBooleanSetting("silkscreenVisible", config.show_silkscreen, "silkscreenCheckbox", silkscreenVisible);
  initBooleanSetting("referencesVisible", true, "referencesCheckbox", referencesVisible);
  initBooleanSetting("valuesVisible", false, "valuesCheckbox", valuesVisible);
  if ("tracks" in pcbdata) {
    initBooleanSetting("tracksVisible", true, "tracksCheckbox", tracksVisible);
    initBooleanSetting("zonesVisible", true, "zonesCheckbox", zonesVisible);
  } else {
    document.getElementById("tracksAndZonesCheckboxes").style.display = "none";
    tracksVisible(false);
    zonesVisible(false);
  }
  initBooleanSetting("dnpOutline", false, "dnpOutlineCheckbox", dnpOutline);
  initBooleanSetting("redrawOnDrag", config.redraw_on_drag, "dragCheckbox", setRedrawOnDrag);
  initBooleanSetting("showCrosshair", config.show_crosshair, "crosshairCheckbox", setShowCrosshair);
  initBooleanSetting("darkmode", config.dark_mode, "darkmodeCheckbox", setDarkMode);
  initBooleanSetting("highlightpin1", config.highlight_pin1, "highlightpin1Checkbox", setHighlightPin1);
  settings.boardRotation = readStorage("boardRotation");
  if (settings.boardRotation === null) {
    settings.boardRotation = config.board_rotation * 5;
  } else {
    settings.boardRotation = parseInt(settings.boardRotation);
  }
  document.getElementById("boardRotation").value = settings.boardRotation / 5;
  document.getElementById("rotationDegree").textContent = settings.boardRotation;
}

// Helper classes for user js callbacks.

const IBOM_EVENT_TYPES = {
  ALL: "all",
  HIGHLIGHT_EVENT: "highlightEvent",
  CHECKBOX_CHANGE_EVENT: "checkboxChangeEvent",
  BOM_BODY_CHANGE_EVENT: "bomBodyChangeEvent",
}

const EventHandler = {
  callbacks: {},
  init: function() {
    for (eventType of Object.values(IBOM_EVENT_TYPES))
      this.callbacks[eventType] = [];
  },
  registerCallback: function(eventType, callback) {
    this.callbacks[eventType].push(callback);
  },
  emitEvent: function(eventType, eventArgs) {
    event = {
      eventType: eventType,
      args: eventArgs,
    }
    var callback;
    for(callback of this.callbacks[eventType])
      callback(event);
    for(callback of this.callbacks[IBOM_EVENT_TYPES.ALL])
      callback(event);
  }
}
EventHandler.init();

///////////////////////////////////////////////

///////////////////////////////////////////////
/* PCB rendering code */

var emptyContext2d = document.createElement("canvas").getContext("2d");
var hitTestContext2d = document.createElement("canvas").getContext("2d");

function deg2rad(deg) {
  return deg * Math.PI / 180;
}

function calcFontPoint(linepoint, text, offsetx, offsety, tilt) {
  var point = [
    linepoint[0] * text.width + offsetx,
    linepoint[1] * text.height + offsety
  ];
  // This approximates pcbnew behavior with how text tilts depending on horizontal justification
  point[0] -= (linepoint[1] + 0.5 * (1 + text.justify[0])) * text.height * tilt;
  return point;
}

function drawText(ctx, text, color) {
  if ("ref" in text && !settings.renderReferences) return;
  if ("val" in text && !settings.renderValues) return;
  ctx.save();
  ctx.fillStyle = color;
  ctx.strokeStyle = color;
  ctx.lineCap = "round";
  ctx.lineJoin = "round";
  ctx.lineWidth = text.thickness;

  if ("svgpath" in text) {    
    // TODO: This path must be cached!
    const path = new Path2D(text.svgpath);
    if(text.useTrueTypeFontRendering) {            
      ctx.fill(path);
    } else {
      ctx.stroke(path);
    }
    
    ctx.restore();
    return;
  }

  ctx.translate(...text.pos);
  ctx.translate(text.thickness * 0.5, 0);
  var angle = -text.angle;
  if (text.attr.includes("mirrored")) {
    ctx.scale(-1, 1);
    angle = -angle;
  }
  var tilt = 0;
  if (text.attr.includes("italic")) {
    tilt = 0.125;
  }
  var interline = text.height * 1.5 + text.thickness;
  var txt = text.text.split("\n");
  // KiCad ignores last empty line.
  if (txt[txt.length - 1] == '') txt.pop();
  ctx.rotate(deg2rad(angle));
  var offsety = (1 - text.justify[1]) / 2 * text.height; // One line offset
  offsety -= (txt.length - 1) * (text.justify[1] + 1) / 2 * interline; // Multiline offset
  for (var i in txt) {
    var lineWidth = text.thickness + interline / 2 * tilt;
    for (var j = 0; j < txt[i].length; j++) {
      if (txt[i][j] == '\t') {
        var fourSpaces = 4 * pcbdata.font_data[' '].w * text.width;
        lineWidth += fourSpaces - lineWidth % fourSpaces;
      } else {
        if (txt[i][j] == '~') {
          j++;
          if (j == txt[i].length)
            break;
        }
        lineWidth += pcbdata.font_data[txt[i][j]].w * text.width;
      }
    }
    var offsetx = -lineWidth * (text.justify[0] + 1) / 2;
    var inOverbar = false;
    for (var j = 0; j < txt[i].length; j++) {
      if (txt[i][j] == '\t') {
        var fourSpaces = 4 * pcbdata.font_data[' '].w * text.width;
        offsetx += fourSpaces - offsetx % fourSpaces;
        continue;
      } else if (txt[i][j] == '~') {
        j++;
        if (j == txt[i].length)
          break;
        if (txt[i][j] != '~') {
          inOverbar = !inOverbar;
        }
      }
      var glyph = pcbdata.font_data[txt[i][j]];
      if (inOverbar) {
        var overbarStart = [offsetx, -text.height * 1.4 + offsety];
        var overbarEnd = [offsetx + text.width * glyph.w, overbarStart[1]];

        if (!lastHadOverbar) {
          overbarStart[0] += text.height * 1.4 * tilt;
          lastHadOverbar = true;
        }
        ctx.beginPath();
        ctx.moveTo(...overbarStart);
        ctx.lineTo(...overbarEnd);
        ctx.stroke();
      } else {
        lastHadOverbar = false;
      }
      for (var line of glyph.l) {
        ctx.beginPath();
        ctx.moveTo(...calcFontPoint(line[0], text, offsetx, offsety, tilt));
        for (var k = 1; k < line.length; k++) {
          ctx.lineTo(...calcFontPoint(line[k], text, offsetx, offsety, tilt));
        }
        ctx.stroke();
      }
      offsetx += glyph.w * text.width;
    }
    offsety += interline;
  }
  ctx.restore();
}

function drawedge(ctx, scalefactor, edge, color) {
  ctx.strokeStyle = color;
  ctx.lineWidth = Math.max(1 / scalefactor, edge.width);
  ctx.lineCap = "round";
  if ("svgpath" in edge) {
    ctx.stroke(new Path2D(edge.svgpath));
  } else {
    ctx.beginPath();
    if (edge.type == "segment") {
      ctx.moveTo(...edge.start);
      ctx.lineTo(...edge.end);
    }
    if (edge.type == "rect") {
      ctx.moveTo(...edge.start);
      ctx.lineTo(edge.start[0], edge.end[1]);
      ctx.lineTo(...edge.end);
      ctx.lineTo(edge.end[0], edge.start[1]);
      ctx.lineTo(...edge.start);
    }
    if (edge.type == "arc") {
      ctx.arc(
        ...edge.start,
        edge.radius,
        deg2rad(edge.startangle),
        deg2rad(edge.endangle));
    }
    if (edge.type == "circle") {
      ctx.arc(
        ...edge.start,
        edge.radius,
        0, 2 * Math.PI);
      ctx.closePath();
    }
    if (edge.type == "curve") {
      ctx.moveTo(...edge.start);
      ctx.bezierCurveTo(...edge.cpa, ...edge.cpb, ...edge.end);
    }
    ctx.stroke();
  }
}

function getChamferedRectPath(size, radius, chamfpos, chamfratio) {
  // chamfpos is a bitmask, left = 1, right = 2, bottom left = 4, bottom right = 8
  var path = new Path2D();
  var width = size[0];
  var height = size[1];
  var x = width * -0.5;
  var y = height * -0.5;
  var chamfOffset = Math.min(width, height) * chamfratio;
  path.moveTo(x, 0);
  if (chamfpos & 4) {
    path.lineTo(x, y + height - chamfOffset);
    path.lineTo(x + chamfOffset, y + height);
    path.lineTo(0, y + height);
  } else {
    path.arcTo(x, y + height, x + width, y + height, radius);
  }
  if (chamfpos & 8) {
    path.lineTo(x + width - chamfOffset, y + height);
    path.lineTo(x + width, y + height - chamfOffset);
    path.lineTo(x + width, 0);
  } else {
    path.arcTo(x + width, y + height, x + width, y, radius);
  }
  if (chamfpos & 2) {
    path.lineTo(x + width, y + chamfOffset);
    path.lineTo(x + width - chamfOffset, y);
    path.lineTo(0, y);
  } else {
    path.arcTo(x + width, y, x, y, radius);
  }
  if (chamfpos & 1) {
    path.lineTo(x + chamfOffset, y);
    path.lineTo(x, y + chamfOffset);
    path.lineTo(x, 0);
  } else {
    path.arcTo(x, y, x, y + height, radius);
  }
  path.closePath();
  return path;
}

function getOblongPath(size) {
  return getChamferedRectPath(size, Math.min(size[0], size[1]) / 2, 0, 0);
}

function getPolygonsPath(shape) {
  if (shape.path2d) {
    return shape.path2d;
  }
  if ("svgpath" in shape) {
    shape.path2d = new Path2D(shape.svgpath);
  } else {
    var path = new Path2D();
    for (var polygon of shape.polygons) {
      path.moveTo(...polygon[0]);
      for (var i = 1; i < polygon.length; i++) {
        path.lineTo(...polygon[i]);
      }
      path.closePath();
    }
    shape.path2d = path;
  }
  return shape.path2d;
}

function drawPolygonShape(ctx, shape, color) {
  ctx.save();
  ctx.fillStyle = color;
  if (!("svgpath" in shape)) {
    ctx.translate(...shape.pos);
    ctx.rotate(deg2rad(-shape.angle));
  }
  ctx.fill(getPolygonsPath(shape));
  ctx.restore();
}


function drawPolylineShape(ctx, shape, color) {
  ctx.save();
  ctx.strokeStyle = color;
  ctx.lineWidth = shape.width;
  if (!("svgpath" in shape)) {
    ctx.translate(...shape.pos);
    ctx.rotate(deg2rad(-shape.angle));
  }
  ctx.stroke(getPolygonsPath(shape));
  ctx.restore();
}

function drawDrawing(ctx, scalefactor, drawing, color) {  
  if (["segment", "arc", "circle", "curve"].includes(drawing.type)) {
    drawedge(ctx, scalefactor, drawing, color);
  } else if (drawing.type == "polygon") {
    drawPolygonShape(ctx, drawing, color);
  } else if (drawing.type == "text") {    
    drawText(ctx, drawing, color);
  } else if (drawing.type == "polyline") {    
    drawPolylineShape(ctx, drawing, color);
  }
}

function getCirclePath(radius) {
  var path = new Path2D();
  path.arc(0, 0, radius, 0, 2 * Math.PI);
  path.closePath();
  return path;
}

function getCachedPadPath(pad) {
  if (!pad.path2d) {
    // if path2d is not set, build one and cache it on pad object
    if (pad.shape == "rect") {
      pad.path2d = new Path2D();
      pad.path2d.rect(...pad.size.map(c => -c * 0.5), ...pad.size);
    } else if (pad.shape == "oval") {
      pad.path2d = getOblongPath(pad.size);
    } else if (pad.shape == "circle") {
      pad.path2d = getCirclePath(pad.size[0] / 2);
    } else if (pad.shape == "roundrect") {
      pad.path2d = getChamferedRectPath(pad.size, pad.radius, 0, 0);
    } else if (pad.shape == "chamfrect") {
      pad.path2d = getChamferedRectPath(pad.size, pad.radius, pad.chamfpos, pad.chamfratio)
    } else if (pad.shape == "custom") {
      pad.path2d = getPolygonsPath(pad);
    } else if(pad.shape === "polygon") {      
      pad.path2d = new Path2D();
      if(pad.polygon.length > 1) {
        const pos = {
          x: pad.pos[0],
          y: pad.pos[1]
        };

        pad.path2d.moveTo(pad.polygon[0].x - pos.x, pad.polygon[0].y - pos.y);
        for (var i = 1; i < pad.polygon.length; i++) {
          const point = pad.polygon[i];          
          pad.path2d.lineTo(point.x - pos.x, point.y - pos.y);
        }
        pad.path2d.closePath();              
      }
    }
  }
  return pad.path2d;
}

function drawPad(ctx, pad, color, outline) {
  ctx.save();
  ctx.translate(...pad.pos);
  if(pad.shape !== 'polygon') {
    ctx.rotate(deg2rad(pad.angle));  
  } else {
    ctx.rotate(deg2rad(0));  
  }
  
  if (pad.offset) {
    ctx.translate(...pad.offset);
  }
  ctx.fillStyle = color;
  ctx.strokeStyle = color;
  var path = getCachedPadPath(pad);
  if (outline) {
    ctx.stroke(path);
  } else {
    ctx.fill(path);
  }
  ctx.restore();
}

function drawPadHole(ctx, pad, padHoleColor) {
  if (pad.type != "th") {
    return
  };

  ctx.save();
  ctx.translate(pad.holeCenterPoint.x, pad.holeCenterPoint.y);    
  ctx.rotate(deg2rad(pad.angle));
  ctx.fillStyle = padHoleColor;
  if (pad.drillshape == "oblong") {
    ctx.fill(getOblongPath(pad.drillsize));
  } else {
    ctx.fill(getCirclePath(pad.drillsize[0] / 2));
  }
  ctx.restore();
}

function drawFootprint(ctx, layer, scalefactor, footprint, padColor, padHoleColor, outlineColor, highlight, outline) {
  if (highlight) {
    // draw bounding box
    if (footprint.layer == layer) {
      ctx.save();
      ctx.globalAlpha = 0.2;
      ctx.translate(...footprint.bbox.pos);
      ctx.rotate(deg2rad(-footprint.bbox.angle));
      ctx.translate(...footprint.bbox.relpos);
      ctx.fillStyle = padColor;
      ctx.fillRect(0, 0, ...footprint.bbox.size);
      ctx.globalAlpha = 1;
      ctx.strokeStyle = padColor;
      ctx.strokeRect(0, 0, ...footprint.bbox.size);
      ctx.restore();
    }
  }
  // draw drawings
  for (var drawing of footprint.drawings) {
    if (drawing.layer == layer) {
      drawDrawing(ctx, scalefactor, drawing.drawing, padColor);
    }
  }
  // draw pads
  if (settings.renderPads) {
    for (var pad of footprint.pads) {
      if (pad.layers.includes(layer)) {
        drawPad(ctx, pad, padColor, outline);
        if (pad.pin1 && settings.highlightpin1) {
          drawPad(ctx, pad, outlineColor, true);
        }
      }
    }
    for (var pad of footprint.pads) {
      drawPadHole(ctx, pad, padHoleColor);
    }
  }
}

function drawCrosshair(canvas, x, y, scalefactor, color) {
  if(!settings.showCrosshair) {
    return;
  }

  var ctx = canvas.getContext("2d");

  HTMLFormControlsCollection.log
  
  ctx.save();
  ctx.globalAlpha = 0.75;
  ctx.lineWidth = 2 / scalefactor;
  ctx.strokeStyle = color;

  // TODO: Should calculate a proper bbox for the view port.
  const dummyOffset = 4000;

  // horz line
  ctx.beginPath();
  ctx.moveTo(x - dummyOffset, y);
  ctx.lineTo(x + dummyOffset, y);
  ctx.stroke();

  // vert line
  ctx.beginPath();
  ctx.moveTo(x, y - dummyOffset);
  ctx.lineTo(x, y + dummyOffset);
  ctx.stroke();

  ctx.globalAlpha = 1;
  ctx.restore();
}

function drawEdgeCuts(canvas, scalefactor) {
  var ctx = canvas.getContext("2d");
  var edgecolor = getComputedStyle(topmostdiv).getPropertyValue('--pcb-edge-color');
  for (var edge of pcbdata.edges) {
    drawedge(ctx, scalefactor, edge, edgecolor);
  }
}

function drawOrphanPads(canvas, layer, scalefactor, highlight, highlightedPads) {
  if (!settings.renderPads) {
    return;
  }

  highlightedPads = highlightedPads || [];

  var ctx = canvas.getContext("2d");
  ctx.save();
  ctx.lineWidth = 3 / scalefactor;
  var style = getComputedStyle(topmostdiv);
  var padColor = style.getPropertyValue('--pad-color');
  var padHoleColor = style.getPropertyValue('--pad-hole-color');  
  if (highlight) {
    padColor = style.getPropertyValue('--pad-color-highlight');
    outlineColor = style.getPropertyValue('--pin1-outline-color-highlight');
  }

  var i = 0;
  for (var pad of pcbdata.pads) {
    if (pad.layers.includes(layer)) {
      var outline = settings.renderDnpOutline;
      if (!highlight || highlightedPads.includes(i)) {
        drawPad(ctx, pad, padColor, outline); 
      }     
    }

    i++;
  }
  
  for (var pad of pcbdata.pads) {
    drawPadHole(ctx, pad, padHoleColor);
  }  

  ctx.restore();
}

function drawFootprints(canvas, layer, scalefactor, highlight) {
  var ctx = canvas.getContext("2d");
  ctx.save();
  ctx.lineWidth = 3 / scalefactor;
  var style = getComputedStyle(topmostdiv);
  var padColor = style.getPropertyValue('--pad-color');
  var padHoleColor = style.getPropertyValue('--pad-hole-color');
  var outlineColor = style.getPropertyValue('--pin1-outline-color');
  if (highlight) {
    padColor = style.getPropertyValue('--pad-color-highlight');
    outlineColor = style.getPropertyValue('--pin1-outline-color-highlight');
  }
  for (var i = 0; i < pcbdata.footprints.length; i++) {
    var mod = pcbdata.footprints[i];
    var outline = settings.renderDnpOutline && pcbdata.bom.skipped.includes(i);
    if (!highlight || highlightedFootprints.includes(i)) {
      drawFootprint(ctx, layer, scalefactor, mod, padColor, padHoleColor, outlineColor, highlight, outline);
    }
  }
  ctx.restore();
}

function drawBgLayer(layername, canvas, layer, scalefactor, edgeColor, polygonColor, textColor) {
  var ctx = canvas.getContext("2d");
  for (var d of pcbdata.drawings[layername][layer]) {
    if (["segment", "arc", "circle", "curve", "rect","polyline"].includes(d.type)) {
      drawedge(ctx, scalefactor, d, edgeColor);
    } else if (d.type == "polygon") {
      drawPolygonShape(ctx, d, polygonColor);
    } else if (d.type == "text") {
      drawText(ctx, d, polygonColor);
    }
  }
}

function drawTracks(canvas, layer, color, highlight) {
  ctx = canvas.getContext("2d");
  ctx.strokeStyle = color;
  ctx.lineCap = "round";
  for(var track of pcbdata.tracks[layer]) {
    if (highlight && highlightedNet != track.net) continue;
    ctx.lineWidth = track.width;

    if(track.type === 'polyline') {
      drawPolylineShape(ctx,track,color);
    } else if(track.type === 'polygon') {
      drawPolygonShape(ctx, track, color);
    } else if(track.type === 'text') {
      drawText(ctx, track, color);
    } else {
      if ('radius' in track) {
        ctx.beginPath();
        ctx.arc(
            ...track.center,
            track.radius,
            deg2rad(track.startangle),
            deg2rad(track.endangle));
        ctx.stroke();
      } else if('start' in track && 'end' in track) {
        ctx.beginPath();
        ctx.moveTo(...track.start);
        ctx.lineTo(...track.end);
        ctx.stroke();
      }
      
    }

  }
}

function drawZones(canvas, layer, color, highlight) {
  ctx = canvas.getContext("2d");
  ctx.save();
  ctx.strokeStyle = color;
  ctx.fillStyle = color;
  ctx.lineJoin = "round";
  for(var zone of pcbdata.zones[layer]) {
    if (!zone.path2d) {
      zone.path2d = getPolygonsPath(zone);
    }
    if (highlight && highlightedNet != zone.net) continue;
    ctx.fill(zone.path2d);
    if (zone.width > 0) {
      ctx.lineWidth = zone.width;
      ctx.stroke(zone.path2d);
    }
  }
  ctx.restore();
}

function clearCanvas(canvas, color = null) {
  var ctx = canvas.getContext("2d");
  ctx.save();
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  if (color) {
    ctx.fillStyle = color;
    ctx.fillRect(0, 0, canvas.width, canvas.height);
  } else {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
  }
  ctx.restore();
}

function drawNets(canvas, layer, highlight) {
  var style = getComputedStyle(topmostdiv);
  if (settings.renderTracks) {
    var trackColor = style.getPropertyValue(highlight ? '--track-color-highlight' : '--track-color');
    drawTracks(canvas, layer, trackColor, highlight);
  }
  if (settings.renderZones) {
    var zoneColor = style.getPropertyValue(highlight ? '--zone-color-highlight' : '--zone-color');
    drawZones(canvas, layer, zoneColor, highlight);
  }
  if (highlight && settings.renderPads) {
    var padColor = style.getPropertyValue('--pad-color-highlight');
    var padHoleColor = style.getPropertyValue('--pad-hole-color');
    var ctx = canvas.getContext("2d");
    for (var footprint of pcbdata.footprints) {
      // draw pads
      var padDrawn = false;
      for (var pad of footprint.pads) {
        if (highlightedNet != pad.net) continue;
        if (pad.layers.includes(layer)) {
          drawPad(ctx, pad, padColor, false);
          padDrawn = true;
        }
      }
      if (padDrawn) {
        // redraw all pad holes because some pads may overlap
        for (var pad of footprint.pads) {
          drawPadHole(ctx, pad, padHoleColor);
        }
      }
    }
  }
}

function drawHighlightsOnLayer(canvasdict, clear = true) {
  if (clear) {
    clearCanvas(canvasdict.highlight);
  }
  
  if (highlightedFootprints.length > 0) {
    drawFootprints(canvasdict.highlight, canvasdict.layer,
      canvasdict.transform.s * canvasdict.transform.zoom, true);
  }

  // Draw crosshairs
  if (highlightedFootprints.length > 0) {
    for(var i = 0; i < pcbdata.footprints.length; i++) {
      const footprint = pcbdata.footprints[i];
      if(highlightedFootprints.includes(i) && footprint.layer === canvasdict.layer) {
        drawCrosshair(canvasdict.highlight, footprint.center[0], footprint.center[1], canvasdict.transform.s * canvasdict.transform.zoom, 'red');
      }
    }
  }

  if (highlightedNet !== null) {
    var highlightedPads = [];
    for(var i = 0; i < pcbdata.pads.length; i++) {
      var pad = pcbdata.pads[i];
      if(pad.net === highlightedNet) {
        highlightedPads.push(i);
      }
    }
    
    drawOrphanPads(canvasdict.highlight, canvasdict.layer,
      canvasdict.transform.s * canvasdict.transform.zoom, true, highlightedPads);

    drawNets(canvasdict.highlight, canvasdict.layer, true);
  }
}

function drawHighlights() {
  drawHighlightsOnLayer(allcanvas.front);
  drawHighlightsOnLayer(allcanvas.back);
}

function drawBackground(canvasdict, clear = true) {
  if (clear) {
    clearCanvas(canvasdict.bg);
    clearCanvas(canvasdict.fab);
    clearCanvas(canvasdict.silk);
  }

  drawNets(canvasdict.bg, canvasdict.layer, false);

  drawOrphanPads(canvasdict.bg, canvasdict.layer, canvasdict.transform.s * canvasdict.transform.zoom, false);

  drawFootprints(canvasdict.bg, canvasdict.layer, canvasdict.transform.s * canvasdict.transform.zoom, false);

  drawEdgeCuts(canvasdict.bg, canvasdict.transform.s);

  var style = getComputedStyle(topmostdiv);
  var edgeColor = style.getPropertyValue('--silkscreen-edge-color');
  var polygonColor = style.getPropertyValue('--silkscreen-polygon-color');
  var textColor = style.getPropertyValue('--silkscreen-text-color');
  if (settings.renderSilkscreen) {
    drawBgLayer(
      "silkscreen", canvasdict.silk, canvasdict.layer,
      canvasdict.transform.s * canvasdict.transform.zoom,
      edgeColor, polygonColor, textColor);
  }
  edgeColor = style.getPropertyValue('--fabrication-edge-color');
  polygonColor = style.getPropertyValue('--fabrication-polygon-color');
  textColor = style.getPropertyValue('--fabrication-text-color');
  if (settings.renderFabrication) {
    drawBgLayer(
      "fabrication", canvasdict.fab, canvasdict.layer,
      canvasdict.transform.s * canvasdict.transform.zoom,
      edgeColor, polygonColor, textColor);
  }
}

function prepareCanvas(canvas, flip, transform) {
  var ctx = canvas.getContext("2d");
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  var fontsize = 1.55;
  ctx.scale(transform.zoom, transform.zoom);
  ctx.translate(transform.panx, transform.pany);
  if (flip) {
    ctx.scale(-1, 1);
  }
  ctx.translate(transform.x, transform.y);
  ctx.rotate(deg2rad(settings.boardRotation));
  ctx.scale(transform.s, transform.s);
}

function prepareLayer(canvasdict) {
  var flip = (canvasdict.layer == "B");
  for (var c of ["bg", "fab", "silk", "highlight"]) {
    prepareCanvas(canvasdict[c], flip, canvasdict.transform);
  }
}

function rotateVector(v, angle) {
  angle = deg2rad(angle);
  return [
    v[0] * Math.cos(angle) - v[1] * Math.sin(angle),
    v[0] * Math.sin(angle) + v[1] * Math.cos(angle)
  ];
}

function applyRotation(bbox) {
  var corners = [
    [bbox.minx, bbox.miny],
    [bbox.minx, bbox.maxy],
    [bbox.maxx, bbox.miny],
    [bbox.maxx, bbox.maxy],
  ];
  corners = corners.map((v) => rotateVector(v, settings.boardRotation));
  return {
    minx: corners.reduce((a, v) => Math.min(a, v[0]), Infinity),
    miny: corners.reduce((a, v) => Math.min(a, v[1]), Infinity),
    maxx: corners.reduce((a, v) => Math.max(a, v[0]), -Infinity),
    maxy: corners.reduce((a, v) => Math.max(a, v[1]), -Infinity),
  }
}

function recalcLayerScale(layerdict, width, height) {
  var bbox = applyRotation(pcbdata.edges_bbox);
  var scalefactor = 0.98 * Math.min(
    width / (bbox.maxx - bbox.minx),
    height / (bbox.maxy - bbox.miny)
  );
  if (scalefactor < 0.1) {
    scalefactor = 1;
  }
  layerdict.transform.s = scalefactor;
  var flip = (layerdict.layer == "B");
  if (flip) {
    layerdict.transform.x = -((bbox.maxx + bbox.minx) * scalefactor + width) * 0.5;
  } else {
    layerdict.transform.x = -((bbox.maxx + bbox.minx) * scalefactor - width) * 0.5;
  }
  layerdict.transform.y = -((bbox.maxy + bbox.miny) * scalefactor - height) * 0.5;
  for (var c of ["bg", "fab", "silk", "highlight"]) {
    canvas = layerdict[c];
    canvas.width = width;
    canvas.height = height;
    canvas.style.width = (width / devicePixelRatio) + "px";
    canvas.style.height = (height / devicePixelRatio) + "px";
  }
}

function redrawCanvas(layerdict) {
  prepareLayer(layerdict);
  drawBackground(layerdict);
  drawHighlightsOnLayer(layerdict);
}

function resizeCanvas(layerdict) {
  var canvasdivid = {
    "F": "frontcanvas",
    "B": "backcanvas"
  } [layerdict.layer];
  var width = document.getElementById(canvasdivid).clientWidth * devicePixelRatio;
  var height = document.getElementById(canvasdivid).clientHeight * devicePixelRatio;
  recalcLayerScale(layerdict, width, height);
  redrawCanvas(layerdict);
}

function resizeAll() {
  resizeCanvas(allcanvas.front);
  resizeCanvas(allcanvas.back);
}

function pointWithinDistanceToSegment(x, y, x1, y1, x2, y2, d) {
  var A = x - x1;
  var B = y - y1;
  var C = x2 - x1;
  var D = y2 - y1;

  var dot = A * C + B * D;
  var len_sq = C * C + D * D;
  var dx, dy;
  if (len_sq == 0) {
    // start and end of the segment coincide
    dx = x - x1;
    dy = y - y1;
  } else {
    var param = dot / len_sq;
    var xx, yy;
    if (param < 0) {
      xx = x1;
      yy = y1;
    } else if (param > 1) {
      xx = x2;
      yy = y2;
    } else {
      xx = x1 + param * C;
      yy = y1 + param * D;
    }
    dx = x - xx;
    dy = y - yy;
  }
  return dx * dx + dy * dy <= d * d;
}

function modulo(n, mod) {
  return ((n % mod) + mod ) % mod;
}

function pointWithinDistanceToArc(x, y, xc, yc, radius, startangle, endangle, d) {
  var dx = x - xc;
  var dy = y - yc;
  var r_sq = dx * dx + dy * dy;
  var rmin = Math.max(0, radius-d);
  var rmax = radius + d;

  if (r_sq < rmin * rmin || r_sq > rmax * rmax)
    return false;

  var angle1 = modulo(deg2rad(startangle), 2 * Math.PI);
  var dx1 = xc + radius * Math.cos(angle1) - x;
  var dy1 = yc + radius * Math.sin(angle1) - y;
  if (dx1 * dx1 + dy1 * dy1 <= d * d)
    return true;

  var angle2 = modulo(deg2rad(endangle), 2 * Math.PI);
  var dx2 = xc + radius * Math.cos(angle2) - x;
  var dy2 = yc + radius * Math.sin(angle2) - y;
  if (dx2 * dx2 + dy2 * dy2 <= d * d)
    return true;

  var angle = modulo(Math.atan2(dy, dx), 2 * Math.PI);
  if (angle1 > angle2)
    return (angle >= angle2 || angle <= angle1);
  else
    return (angle >= angle1 && angle <= angle2);
}

function pointWithinPad(x, y, pad) {
  var v = [x - pad.pos[0], y - pad.pos[1]];
  v = rotateVector(v, -pad.angle);
  if (pad.offset) {
    v[0] -= pad.offset[0];
    v[1] -= pad.offset[1];
  }
  return emptyContext2d.isPointInPath(getCachedPadPath(pad), ...v);
}

function netHitScan(layer, x, y) {
  // TODO: Should be refactored

  // Check track segments
  if (settings.renderTracks && pcbdata.tracks) {
    for(var track of pcbdata.tracks[layer]) {
      if(track.type === 'polyline') {
        const path = getPolygonsPath(track);
        if(path) {
          hitTestContext2d.save();
          hitTestContext2d.lineWidth = track.width;
          
          if(hitTestContext2d.isPointInStroke(path,x,y)) {
            hitTestContext2d.restore();
            return track.net;            
          }
          
          hitTestContext2d.restore();          
        }        

      } else if(track.type === 'polygon') {
        const path = getPolygonsPath(track);
        if(path && hitTestContext2d.isPointInPath(path,x,y)) {          
          return track.net;                      
        }                     
      } else if(track.type === 'text') {
        // TODO: To implement taking in account TrueType fonts.
      } else if ('radius' in track) {
        if (pointWithinDistanceToArc(x, y, ...track.center, track.radius, track.startangle, track.endangle, track.width / 2)) {
          return track.net;
        }
      } else if('start' in track && 'end' in track) {
        if (pointWithinDistanceToSegment(x, y, ...track.start, ...track.end, track.width / 2)) {
          return track.net;
        }
      }
    }
  }
  // Check pads
  if (settings.renderPads) {

    // Footprints containing pads
    for (var footprint of pcbdata.footprints) {
      for(var pad of footprint.pads) {
        if (pad.layers.includes(layer) && pointWithinPad(x, y, pad)) {
          return pad.net;
        }
      }
    }

    // Orphan pads
    for(var pad of pcbdata.pads) {
      if (pad.layers.includes(layer) && pointWithinPad(x, y, pad)) {
        return pad.net;
      }
    }
  }
  return null;
}

function pointWithinFootprintBbox(x, y, bbox) {
  var v = [x - bbox.pos[0], y - bbox.pos[1]];
  v = rotateVector(v, bbox.angle);
  return bbox.relpos[0] <= v[0] && v[0] <= bbox.relpos[0] + bbox.size[0] &&
         bbox.relpos[1] <= v[1] && v[1] <= bbox.relpos[1] + bbox.size[1];
}

function bboxHitScan(layer, x, y) {
  var result = [];
  for (var i = 0; i < pcbdata.footprints.length; i++) {
    var footprint = pcbdata.footprints[i];
    if (footprint.layer == layer) {
      if (pointWithinFootprintBbox(x, y, footprint.bbox)) {
        result.push(i);
      }
    }
  }
  return result;
}

function handlePointerDown(e, layerdict) {
  if (e.button != 0 && e.button != 1) {
    return;
  }
  e.preventDefault();
  e.stopPropagation();

  if (!e.hasOwnProperty("offsetX")) {
    // The polyfill doesn't set this properly
    e.offsetX = e.pageX - e.currentTarget.offsetLeft;
    e.offsetY = e.pageY - e.currentTarget.offsetTop;
  }

  layerdict.pointerStates[e.pointerId] = {
    distanceTravelled: 0,
    lastX: e.offsetX,
    lastY: e.offsetY,
    downTime: Date.now(),
  };
}

function handleMouseClick(e, layerdict) {
  if (!e.hasOwnProperty("offsetX")) {
    // The polyfill doesn't set this properly
    e.offsetX = e.pageX - e.currentTarget.offsetLeft;
    e.offsetY = e.pageY - e.currentTarget.offsetTop;
  }

  var x = e.offsetX;
  var y = e.offsetY;
  var t = layerdict.transform;
  if (layerdict.layer == "B") {
    x = (devicePixelRatio * x / t.zoom - t.panx + t.x) / -t.s;
  } else {
    x = (devicePixelRatio * x / t.zoom - t.panx - t.x) / t.s;
  }
  y = (devicePixelRatio * y / t.zoom - t.y - t.pany) / t.s;
  var v = rotateVector([x, y], -settings.boardRotation);
  if ("nets" in pcbdata) {
    var net = netHitScan(layerdict.layer, ...v);
    if (net !== highlightedNet) {
      netClicked(net);
    }
  }
  if (highlightedNet === null) {
    var footprints = bboxHitScan(layerdict.layer, ...v);
    if (footprints.length > 0) {
      footprintsClicked(footprints);
    }
  }
}

function handlePointerLeave(e, layerdict) {
  e.preventDefault();
  e.stopPropagation();

  if (!settings.redrawOnDrag) {
    redrawCanvas(layerdict);
  }

  delete layerdict.pointerStates[e.pointerId];
}

function resetTransform(layerdict) {
  layerdict.transform.panx = 0;
  layerdict.transform.pany = 0;
  layerdict.transform.zoom = 1;
  redrawCanvas(layerdict);
}

function handlePointerUp(e, layerdict) {
  if (!e.hasOwnProperty("offsetX")) {
    // The polyfill doesn't set this properly
    e.offsetX = e.pageX - e.currentTarget.offsetLeft;
    e.offsetY = e.pageY - e.currentTarget.offsetTop;
  }

  e.preventDefault();
  e.stopPropagation();

  if (e.button == 2) {
    // Reset pan and zoom on right click.
    resetTransform(layerdict);
    layerdict.anotherPointerTapped = false;
    return;
  }

  // We haven't necessarily had a pointermove event since the interaction started, so make sure we update this now
  var ptr = layerdict.pointerStates[e.pointerId];
  ptr.distanceTravelled += Math.abs(e.offsetX - ptr.lastX) + Math.abs(e.offsetY - ptr.lastY);

  if (e.button == 0 && ptr.distanceTravelled < 10 && Date.now() - ptr.downTime <= 500) {
    if (Object.keys(layerdict.pointerStates).length == 1) {
      if (layerdict.anotherPointerTapped) {
        // This is the second pointer coming off of a two-finger tap
        resetTransform(layerdict);
      } else {
        // This is just a regular tap
        handleMouseClick(e, layerdict);
      }
      layerdict.anotherPointerTapped = false;
    } else {
      // This is the first finger coming off of what could become a two-finger tap
      layerdict.anotherPointerTapped = true;
    }
  } else {
    if (!settings.redrawOnDrag) {
      redrawCanvas(layerdict);
    }
    layerdict.anotherPointerTapped = false;
  }

  delete layerdict.pointerStates[e.pointerId];
}

function handlePointerMove(e, layerdict) {
  if (!layerdict.pointerStates.hasOwnProperty(e.pointerId)) {
    return;
  }
  e.preventDefault();
  e.stopPropagation();

  if (!e.hasOwnProperty("offsetX")) {
    // The polyfill doesn't set this properly
    e.offsetX = e.pageX - e.currentTarget.offsetLeft;
    e.offsetY = e.pageY - e.currentTarget.offsetTop;
  }

  var thisPtr = layerdict.pointerStates[e.pointerId];

  var dx = e.offsetX - thisPtr.lastX;
  var dy = e.offsetY - thisPtr.lastY;

  // If this number is low on pointer up, we count the action as a click
  thisPtr.distanceTravelled += Math.abs(dx) + Math.abs(dy);

  if (Object.keys(layerdict.pointerStates).length == 1) {
    // This is a simple drag
    layerdict.transform.panx += devicePixelRatio * dx / layerdict.transform.zoom;
    layerdict.transform.pany += devicePixelRatio * dy / layerdict.transform.zoom;
  } else if (Object.keys(layerdict.pointerStates).length == 2) {
    var otherPtr = Object.values(layerdict.pointerStates).filter((ptr) => ptr != thisPtr)[0];

    var oldDist = Math.sqrt(Math.pow(thisPtr.lastX - otherPtr.lastX, 2) + Math.pow(thisPtr.lastY - otherPtr.lastY, 2));
    var newDist = Math.sqrt(Math.pow(e.offsetX - otherPtr.lastX, 2)     + Math.pow(e.offsetY - otherPtr.lastY, 2));

    var scaleFactor = newDist/oldDist;

    if (scaleFactor != NaN) {
      layerdict.transform.zoom *= scaleFactor;

      var zoomd = (1 - scaleFactor) / layerdict.transform.zoom;
      layerdict.transform.panx += devicePixelRatio * otherPtr.lastX * zoomd;
      layerdict.transform.pany += devicePixelRatio * otherPtr.lastY * zoomd;
    }
  }

  thisPtr.lastX = e.offsetX;
  thisPtr.lastY = e.offsetY;

  if (settings.redrawOnDrag) {
    redrawCanvas(layerdict);
  }
}

function handleMouseWheel(e, layerdict) {
  e.preventDefault();
  e.stopPropagation();
  var t = layerdict.transform;
  var wheeldelta = e.deltaY;
  if (e.deltaMode == 1) {
    // FF only, scroll by lines
    wheeldelta *= 30;
  } else if (e.deltaMode == 2) {
    wheeldelta *= 300;
  }
  var m = Math.pow(1.1, -wheeldelta / 40);
  // Limit amount of zoom per tick.
  if (m > 2) {
    m = 2;
  } else if (m < 0.5) {
    m = 0.5;
  }
  t.zoom *= m;
  var zoomd = (1 - m) / t.zoom;
  t.panx += devicePixelRatio * e.offsetX * zoomd;
  t.pany += devicePixelRatio * e.offsetY * zoomd;
  redrawCanvas(layerdict);
}

function addMouseHandlers(div, layerdict) {
  div.addEventListener("pointerdown", function(e) {
    handlePointerDown(e, layerdict);
  });
  div.addEventListener("pointermove", function(e) {
    handlePointerMove(e, layerdict);
  });
  div.addEventListener("pointerup", function(e) {
    handlePointerUp(e, layerdict);
  });
  var pointerleave = function(e) {
    handlePointerLeave(e, layerdict);
  }
  div.addEventListener("pointercancel", pointerleave);
  div.addEventListener("pointerleave", pointerleave);
  div.addEventListener("pointerout", pointerleave);

  div.onwheel = function(e) {
    handleMouseWheel(e, layerdict);
  }
  for (var element of [div, layerdict.bg, layerdict.fab, layerdict.silk, layerdict.highlight]) {
    element.addEventListener("contextmenu", function(e) {
      e.preventDefault();
    }, false);
  }
}

function setRedrawOnDrag(value) {
  settings.redrawOnDrag = value;
  writeStorage("redrawOnDrag", value);
}

function setShowCrosshair(value) {
  settings.showCrosshair = value;
  writeStorage("showCrosshair", value);
}

function setBoardRotation(value) {
  settings.boardRotation = value * 5;
  writeStorage("boardRotation", settings.boardRotation);
  document.getElementById("rotationDegree").textContent = settings.boardRotation;
  resizeAll();
}

function initRender() {
  allcanvas = {
    front: {
      transform: {
        x: 0,
        y: 0,
        s: 1,
        panx: 0,
        pany: 0,
        zoom: 1,
      },
      pointerStates: {},
      anotherPointerTapped: false,
      bg: document.getElementById("F_bg"),
      fab: document.getElementById("F_fab"),
      silk: document.getElementById("F_slk"),
      highlight: document.getElementById("F_hl"),
      layer: "F",
    },
    back: {
      transform: {
        x: 0,
        y: 0,
        s: 1,
        panx: 0,
        pany: 0,
        zoom: 1,
      },
      pointerStates: {},
      anotherPointerTapped: false,
      bg: document.getElementById("B_bg"),
      fab: document.getElementById("B_fab"),
      silk: document.getElementById("B_slk"),
      highlight: document.getElementById("B_hl"),
      layer: "B",
    }
  };
  addMouseHandlers(document.getElementById("frontcanvas"), allcanvas.front);
  addMouseHandlers(document.getElementById("backcanvas"), allcanvas.back);
}

///////////////////////////////////////////////

///////////////////////////////////////////////
/* DOM manipulation and misc code */

var bomsplit;
var canvassplit;
var initDone = false;
var bomSortFunction = null;
var currentSortColumn = null;
var currentSortOrder = null;
var currentHighlightedRowId;
var highlightHandlers = [];
var footprintIndexToHandler = {};
var netsToHandler = {};
var highlightedFootprints = [];
var highlightedOrphanPads = [];
var highlightedNet = null;
var lastClicked;

function dbg(html) {
  dbgdiv.innerHTML = html;
}

function redrawIfInitDone() {
  if (initDone) {
    redrawCanvas(allcanvas.front);
    redrawCanvas(allcanvas.back);
  }
}

function padsVisible(value) {
  writeStorage("padsVisible", value);
  settings.renderPads = value;
  redrawIfInitDone();
}

function referencesVisible(value) {
  writeStorage("referencesVisible", value);
  settings.renderReferences = value;
  redrawIfInitDone();
}

function valuesVisible(value) {
  writeStorage("valuesVisible", value);
  settings.renderValues = value;
  redrawIfInitDone();
}

function tracksVisible(value) {
  writeStorage("tracksVisible", value);
  settings.renderTracks = value;
  redrawIfInitDone();
}

function zonesVisible(value) {
  writeStorage("zonesVisible", value);
  settings.renderZones = value;
  redrawIfInitDone();
}

function dnpOutline(value) {
  writeStorage("dnpOutline", value);
  settings.renderDnpOutline = value;
  redrawIfInitDone();
}

function setDarkMode(value) {
  if (value) {
    topmostdiv.classList.add("dark");
  } else {
    topmostdiv.classList.remove("dark");
  }
  writeStorage("darkmode", value);
  settings.darkMode = value;
  redrawIfInitDone();
}

function setFullscreen(value) {
  if (value) {
    document.documentElement.requestFullscreen();
  } else {
    document.exitFullscreen();
  }
}

function fabricationVisible(value) {
  writeStorage("fabricationVisible", value);
  settings.renderFabrication = value;
  redrawIfInitDone();
}

function silkscreenVisible(value) {
  writeStorage("silkscreenVisible", value);
  settings.renderSilkscreen = value;
  redrawIfInitDone();
}

function setHighlightPin1(value) {
  writeStorage("highlightpin1", value);
  settings.highlightpin1 = value;
  redrawIfInitDone();
}

function getStoredCheckboxRefs(checkbox) {
  function convert(ref) {
    var intref = parseInt(ref);
    if (isNaN(intref)) {
      for (var i = 0; i < pcbdata.footprints.length; i++) {
        if (pcbdata.footprints[i].ref == ref) {
          return i;
        }
      }
      return -1;
    } else {
      return intref;
    }
  }
  if (!(checkbox in settings.checkboxStoredRefs)) {
    var val = readStorage("checkbox_" + checkbox);
    settings.checkboxStoredRefs[checkbox] = val ? val : "";
  }
  if (!settings.checkboxStoredRefs[checkbox]) {
    return new Set();
  } else {
    return new Set(settings.checkboxStoredRefs[checkbox].split(",").map(r => convert(r)).filter(a => a >= 0));
  }
}

function getCheckboxState(checkbox, references) {
  var storedRefsSet = getStoredCheckboxRefs(checkbox);
  var currentRefsSet = new Set(references.map(r => r[1]));
  // Get difference of current - stored
  var difference = new Set(currentRefsSet);
  for (ref of storedRefsSet) {
    difference.delete(ref);
  }
  if (difference.size == 0) {
    // All the current refs are stored
    return "checked";
  } else if (difference.size == currentRefsSet.size) {
    // None of the current refs are stored
    return "unchecked";
  } else {
    // Some of the refs are stored
    return "indeterminate";
  }
}

function setBomCheckboxState(checkbox, element, references) {
  var state = getCheckboxState(checkbox, references);
  element.checked = (state == "checked");
  element.indeterminate = (state == "indeterminate");
}

function createCheckboxChangeHandler(checkbox, references, row) {
  return function() {
    refsSet = getStoredCheckboxRefs(checkbox);
    var darkenWhenChecked = settings.darkenWhenChecked == checkbox;
    eventArgs = {
      checkbox: checkbox,
      refs: references,
    }
    if (this.checked) {
      // checkbox ticked
      for (var ref of references) {
        refsSet.add(ref[1]);
      }
      if (darkenWhenChecked) {
        row.classList.add("checked");
      }
      eventArgs.state = 'checked';
    } else {
      // checkbox unticked
      for (var ref of references) {
        refsSet.delete(ref[1]);
      }
      if (darkenWhenChecked) {
        row.classList.remove("checked");
      }
      eventArgs.state = 'unchecked';
    }
    settings.checkboxStoredRefs[checkbox] = [...refsSet].join(",");
    writeStorage("checkbox_" + checkbox, settings.checkboxStoredRefs[checkbox]);
    updateCheckboxStats(checkbox);
    EventHandler.emitEvent(IBOM_EVENT_TYPES.CHECKBOX_CHANGE_EVENT, eventArgs);
  }
}

function clearHighlightedFootprints() {
  if (currentHighlightedRowId) {
    document.getElementById(currentHighlightedRowId).classList.remove("highlighted");
    currentHighlightedRowId = null;
    highlightedFootprints = [];  
    highlightedOrphanPads = [];  
    highlightedNet = null;
  }
}

function createRowHighlightHandler(rowid, refs, net) {
  return function() {
    if (currentHighlightedRowId) {
      if (currentHighlightedRowId == rowid) {
        return;
      }
      document.getElementById(currentHighlightedRowId).classList.remove("highlighted");
    }
    document.getElementById(rowid).classList.add("highlighted");
    currentHighlightedRowId = rowid;
    highlightedFootprints = refs ? refs.map(r => r[1]) : [];
    highlightedNet = net;
    drawHighlights();
    EventHandler.emitEvent(
      IBOM_EVENT_TYPES.HIGHLIGHT_EVENT,
      {
        rowid: rowid,
        refs: refs,
        net: net
      });
  }
}

function entryMatches(entry) {
  if (settings.bommode == "netlist") {
    // entry is just a net name
    return entry.toLowerCase().indexOf(filter) >= 0;
  }
  // check refs
  for (var ref of entry[3]) {
    if (ref[0].toLowerCase().indexOf(filter) >= 0) {
      return true;
    }
  }
  // check extra fields
  for (var i in config.extra_fields) {
    if (entry[4][i].toLowerCase().indexOf(filter) >= 0) {
      return true;
    }
  }
  // check value
  if (entry[1].toLowerCase().indexOf(filter) >= 0) {
    return true;
  }
  // check footprint
  if (entry[2].toLowerCase().indexOf(filter) >= 0) {
    return true;
  }
  return false;
}

function findRefInEntry(entry) {
  return entry[3].filter(r => r[0].toLowerCase() == reflookup);
}

function highlightFilter(s) {
  if (!filter) {
    return s;
  }
  var parts = s.toLowerCase().split(filter);
  if (parts.length == 1) {
    return s;
  }
  var r = "";
  var pos = 0;
  for (var i in parts) {
    if (i > 0) {
      r += '<mark class="highlight">' +
        s.substring(pos, pos + filter.length) +
        '</mark>';
      pos += filter.length;
    }
    r += s.substring(pos, pos + parts[i].length);
    pos += parts[i].length;
  }
  return r;
}

function checkboxSetUnsetAllHandler(checkboxname) {
  return function() {
    var checkboxnum = 0;
    while (checkboxnum < settings.checkboxes.length &&
      settings.checkboxes[checkboxnum].toLowerCase() != checkboxname.toLowerCase()) {
      checkboxnum++;
    }
    if (checkboxnum >= settings.checkboxes.length) {
      return;
    }
    var allset = true;
    var checkbox;
    var row;
    for (row of bombody.childNodes) {
      checkbox = row.childNodes[checkboxnum + 1].childNodes[0];
      if (!checkbox.checked || checkbox.indeterminate) {
        allset = false;
        break;
      }
    }
    for (row of bombody.childNodes) {
      checkbox = row.childNodes[checkboxnum + 1].childNodes[0];
      checkbox.checked = !allset;
      checkbox.indeterminate = false;
      checkbox.onchange();
    }
  }
}

function createColumnHeader(name, cls, comparator) {
  var th = document.createElement("TH");
  th.innerHTML = name;
  th.classList.add(cls);
  th.style.cursor = "pointer";
  var span = document.createElement("SPAN");
  span.classList.add("sortmark");
  span.classList.add("none");
  th.appendChild(span);
  th.onclick = function() {
    if (currentSortColumn && this !== currentSortColumn) {
      // Currently sorted by another column
      currentSortColumn.childNodes[1].classList.remove(currentSortOrder);
      currentSortColumn.childNodes[1].classList.add("none");
      currentSortColumn = null;
      currentSortOrder = null;
    }
    if (currentSortColumn && this === currentSortColumn) {
      // Already sorted by this column
      if (currentSortOrder == "asc") {
        // Sort by this column, descending order
        bomSortFunction = function(a, b) {
          return -comparator(a, b);
        }
        currentSortColumn.childNodes[1].classList.remove("asc");
        currentSortColumn.childNodes[1].classList.add("desc");
        currentSortOrder = "desc";
      } else {
        // Unsort
        bomSortFunction = null;
        currentSortColumn.childNodes[1].classList.remove("desc");
        currentSortColumn.childNodes[1].classList.add("none");
        currentSortColumn = null;
        currentSortOrder = null;
      }
    } else {
      // Sort by this column, ascending order
      bomSortFunction = comparator;
      currentSortColumn = this;
      currentSortColumn.childNodes[1].classList.remove("none");
      currentSortColumn.childNodes[1].classList.add("asc");
      currentSortOrder = "asc";
    }
    populateBomBody();
  }
  return th;
}

function populateBomHeader() {
  while (bomhead.firstChild) {
    bomhead.removeChild(bomhead.firstChild);
  }
  var tr = document.createElement("TR");
  var th = document.createElement("TH");
  th.classList.add("numCol");
  tr.appendChild(th);
  var checkboxCompareClosure = function(checkbox) {
    return (a, b) => {
      var stateA = getCheckboxState(checkbox, a[3]);
      var stateB = getCheckboxState(checkbox, b[3]);
      if (stateA > stateB) return -1;
      if (stateA < stateB) return 1;
      return 0;
    }
  }
  if (settings.bommode == "netlist") {
    th = createColumnHeader("Net name", "bom-netname", (a, b) => {
      if (a > b) return -1;
      if (a < b) return 1;
      return 0;
    });
    tr.appendChild(th);
  } else {
    for (var checkbox of settings.checkboxes) {
      th = createColumnHeader(
        checkbox, "bom-checkbox", checkboxCompareClosure(checkbox));
      th.onclick = fancyDblClickHandler(
        th, th.onclick.bind(th), checkboxSetUnsetAllHandler(checkbox));
      tr.appendChild(th);
    }
    tr.appendChild(createColumnHeader("References", "References", (a, b) => {
      var i = 0;
      while (i < a[3].length && i < b[3].length) {
        if (a[3][i] != b[3][i]) return a[3][i] > b[3][i] ? 1 : -1;
        i++;
      }
      return a[3].length - b[3].length;
    }));
    // Extra fields
    if (config.extra_fields.length > 0) {
      var extraFieldCompareClosure = function(fieldIndex) {
        return (a, b) => {
          var fa = a[4][fieldIndex];
          var fb = b[4][fieldIndex];
          if (fa != fb) return fa > fb ? 1 : -1;
          else return 0;
        }
      }
      for (var i in config.extra_fields) {
        tr.appendChild(createColumnHeader(
          config.extra_fields[i], "extra", extraFieldCompareClosure(i)));
      }
    }
    tr.appendChild(createColumnHeader("Value", "Value", (a, b) => {
      return valueCompare(a[5], b[5], a[1], b[1]);
    }));
    tr.appendChild(createColumnHeader("Footprint", "Footprint", (a, b) => {
      if (a[2] != b[2]) return a[2] > b[2] ? 1 : -1;
      else return 0;
    }));
    if (settings.bommode == "grouped") {
      tr.appendChild(createColumnHeader("Quantity", "Quantity", (a, b) => {
        return a[3].length - b[3].length;
      }));
    }
  }
  bomhead.appendChild(tr);
}

function populateBomBody() {
  while (bom.firstChild) {
    bom.removeChild(bom.firstChild);
  }
  highlightHandlers = [];
  footprintIndexToHandler = {};
  netsToHandler = {};
  currentHighlightedRowId = null;
  var first = true;
  if (settings.bommode == "netlist") {
    bomtable = pcbdata.nets.slice();
  } else {
    switch (settings.canvaslayout) {
      case 'F':
        bomtable = pcbdata.bom.F.slice();
        break;
      case 'FB':
        bomtable = pcbdata.bom.both.slice();
        break;
      case 'B':
        bomtable = pcbdata.bom.B.slice();
        break;
    }
    if (settings.bommode == "ungrouped") {
      // expand bom table
      expandedTable = []
      for (var bomentry of bomtable) {
        for (var ref of bomentry[3]) {
          expandedTable.push([1, bomentry[1], bomentry[2], [ref], bomentry[4], bomentry[5]]);
        }
      }
      bomtable = expandedTable;
    }
  }
  if (bomSortFunction) {
    bomtable = bomtable.sort(bomSortFunction);
  }
  for (var i in bomtable) {
    var bomentry = bomtable[i];
    if (filter && !entryMatches(bomentry)) {
      continue;
    }
    var references = null;
    var netname = null;
    var tr = document.createElement("TR");
    var td = document.createElement("TD");
    var rownum = +i + 1;
    tr.id = "bomrow" + rownum;
    td.textContent = rownum;
    tr.appendChild(td);
    if (settings.bommode == "netlist") {
      netname = bomentry;
      td = document.createElement("TD");
      td.innerHTML = highlightFilter(netname ? netname : "&lt;no net&gt;");
      tr.appendChild(td);
    } else {
      if (reflookup) {
        references = findRefInEntry(bomentry);
        if (references.length == 0) {
          continue;
        }
      } else {
        references = bomentry[3];
      }
      // Checkboxes
      for (var checkbox of settings.checkboxes) {
        if (checkbox) {
          td = document.createElement("TD");
          var input = document.createElement("input");
          input.type = "checkbox";
          input.onchange = createCheckboxChangeHandler(checkbox, references, tr);
          setBomCheckboxState(checkbox, input, references);
          if (input.checked && settings.darkenWhenChecked == checkbox) {
            tr.classList.add("checked");
          }
          td.appendChild(input);
          tr.appendChild(td);
        }
      }
      // References
      td = document.createElement("TD");
      td.innerHTML = highlightFilter(references.map(r => r[0]).join(", "));
      tr.appendChild(td);
      // Extra fields
      for (var i in config.extra_fields) {
        td = document.createElement("TD");
        td.innerHTML = highlightFilter(bomentry[4][i]);
        tr.appendChild(td);
      }
      // Value
      td = document.createElement("TD");
      td.innerHTML = highlightFilter(bomentry[1]);
      tr.appendChild(td);
      // Footprint
      td = document.createElement("TD");
      td.innerHTML = highlightFilter(bomentry[2]);
      tr.appendChild(td);
      if (settings.bommode == "grouped") {
        // Quantity
        td = document.createElement("TD");
        td.textContent = bomentry[3].length;
        tr.appendChild(td);
      }
    }
    bom.appendChild(tr);
    var handler = createRowHighlightHandler(tr.id, references, netname);
    tr.onmousemove = handler;
    highlightHandlers.push({
      id: tr.id,
      handler: handler,
    });
    if (references !== null) {
      for (var refIndex of references.map(r => r[1])) {
        footprintIndexToHandler[refIndex] = handler;
      }
    }
    if (netname !== null) {
      netsToHandler[netname] = handler;
    }
    if ((filter || reflookup) && first) {
      handler();
      first = false;
    }
  }
  EventHandler.emitEvent(
    IBOM_EVENT_TYPES.BOM_BODY_CHANGE_EVENT,
    {
      filter: filter,
      reflookup: reflookup,
      checkboxes: settings.checkboxes,
      bommode: settings.bommode,
    });
}

function highlightPreviousRow() {
  if (!currentHighlightedRowId) {
    highlightHandlers[highlightHandlers.length - 1].handler();
  } else {
    if (highlightHandlers.length > 1 &&
      highlightHandlers[0].id == currentHighlightedRowId) {
      highlightHandlers[highlightHandlers.length - 1].handler();
    } else {
      for (var i = 0; i < highlightHandlers.length - 1; i++) {
        if (highlightHandlers[i + 1].id == currentHighlightedRowId) {
          highlightHandlers[i].handler();
          break;
        }
      }
    }
  }
  smoothScrollToRow(currentHighlightedRowId);
}

function highlightNextRow() {
  if (!currentHighlightedRowId) {
    highlightHandlers[0].handler();
  } else {
    if (highlightHandlers.length > 1 &&
      highlightHandlers[highlightHandlers.length - 1].id == currentHighlightedRowId) {
      highlightHandlers[0].handler();
    } else {
      for (var i = 1; i < highlightHandlers.length; i++) {
        if (highlightHandlers[i - 1].id == currentHighlightedRowId) {
          highlightHandlers[i].handler();
          break;
        }
      }
    }
  }
  smoothScrollToRow(currentHighlightedRowId);
}

function populateBomTable() {
  populateBomHeader();
  populateBomBody();
}

function footprintsClicked(footprintIndexes) {
  var lastClickedIndex = footprintIndexes.indexOf(lastClicked);
  for (var i = 1; i <= footprintIndexes.length; i++) {
    var refIndex = footprintIndexes[(lastClickedIndex + i) % footprintIndexes.length];
    if (refIndex in footprintIndexToHandler) {
      lastClicked = refIndex;
      footprintIndexToHandler[refIndex]();
      smoothScrollToRow(currentHighlightedRowId);
      break;
    }
  }
}

function netClicked(net) {
  if (net in netsToHandler) {
    netsToHandler[net]();
    smoothScrollToRow(currentHighlightedRowId);
  } else {
    clearHighlightedFootprints();
    highlightedNet = net;
    drawHighlights();
  }
}

function updateFilter(input) {
  filter = input.toLowerCase();
  populateBomTable();
}

function updateRefLookup(input) {
  reflookup = input.toLowerCase();
  populateBomTable();
}

function changeCanvasLayout(layout) {
  document.getElementById("fl-btn").classList.remove("depressed");
  document.getElementById("fb-btn").classList.remove("depressed");
  document.getElementById("bl-btn").classList.remove("depressed");
  switch (layout) {
    case 'F':
      document.getElementById("fl-btn").classList.add("depressed");
      if (settings.bomlayout != "bom-only") {
        canvassplit.collapse(1);
      }
      break;
    case 'B':
      document.getElementById("bl-btn").classList.add("depressed");
      if (settings.bomlayout != "bom-only") {
        canvassplit.collapse(0);
      }
      break;
    default:
      document.getElementById("fb-btn").classList.add("depressed");
      if (settings.bomlayout != "bom-only") {
        canvassplit.setSizes([50, 50]);
      }
  }
  settings.canvaslayout = layout;
  writeStorage("canvaslayout", layout);
  resizeAll();
  changeBomMode(settings.bommode);
}

function populateMetadata() {
  document.getElementById("title").innerHTML = pcbdata.metadata.title;
  document.getElementById("revision").innerHTML = "Rev: " + pcbdata.metadata.revision;
  document.getElementById("company").innerHTML = pcbdata.metadata.company;
  document.getElementById("filedate").innerHTML = pcbdata.metadata.date;
  if (pcbdata.metadata.title != "") {
    document.title = pcbdata.metadata.title + " BOM";
  }
  // Calculate board stats
  var fp_f = 0, fp_b = 0, pads_f = 0, pads_b = 0, pads_th = 0;
  for (var i = 0; i < pcbdata.footprints.length; i++) {
    if (pcbdata.bom.skipped.includes(i)) continue;
    var mod = pcbdata.footprints[i];
    if (mod.layer == "F") {
      fp_f++;
    } else {
      fp_b++;
    }
    for (var pad of mod.pads) {
      if (pad.type == "th") {
        pads_th++;
      } else {
        if (pad.layers.includes("F")) {
          pads_f++;
        }
        if (pad.layers.includes("B")) {
          pads_b++;
        }
      }
    }
  }
  document.getElementById("stats-components-front").innerHTML = fp_f;
  document.getElementById("stats-components-back").innerHTML = fp_b;
  document.getElementById("stats-components-total").innerHTML = fp_f + fp_b;
  document.getElementById("stats-groups-front").innerHTML = pcbdata.bom.F.length;
  document.getElementById("stats-groups-back").innerHTML = pcbdata.bom.B.length;
  document.getElementById("stats-groups-total").innerHTML = pcbdata.bom.both.length;
  document.getElementById("stats-smd-pads-front").innerHTML = pads_f;
  document.getElementById("stats-smd-pads-back").innerHTML = pads_b;
  document.getElementById("stats-smd-pads-total").innerHTML = pads_f + pads_b;
  document.getElementById("stats-th-pads").innerHTML = pads_th;
  // Update version string
  document.getElementById("github-link").innerHTML = "InteractiveHtmlBom&nbsp;" +
    /^v\d+\.\d+/.exec(pcbdata.ibom_version)[0];
}

function changeBomLayout(layout) {
  document.getElementById("bom-btn").classList.remove("depressed");
  document.getElementById("lr-btn").classList.remove("depressed");
  document.getElementById("tb-btn").classList.remove("depressed");
  switch (layout) {
    case 'bom-only':
      document.getElementById("bom-btn").classList.add("depressed");
      if (bomsplit) {
        bomsplit.destroy();
        bomsplit = null;
        canvassplit.destroy();
        canvassplit = null;
      }
      document.getElementById("frontcanvas").style.display = "none";
      document.getElementById("backcanvas").style.display = "none";
      document.getElementById("bot").style.height = "";
      break;
    case 'top-bottom':
      document.getElementById("tb-btn").classList.add("depressed");
      document.getElementById("frontcanvas").style.display = "";
      document.getElementById("backcanvas").style.display = "";
      document.getElementById("bot").style.height = "calc(100% - 80px)";
      document.getElementById("bomdiv").classList.remove("split-horizontal");
      document.getElementById("canvasdiv").classList.remove("split-horizontal");
      document.getElementById("frontcanvas").classList.add("split-horizontal");
      document.getElementById("backcanvas").classList.add("split-horizontal");
      if (bomsplit) {
        bomsplit.destroy();
        bomsplit = null;
        canvassplit.destroy();
        canvassplit = null;
      }
      bomsplit = Split(['#bomdiv', '#canvasdiv'], {
        sizes: [50, 50],
        onDragEnd: resizeAll,
        direction: "vertical",
        gutterSize: 5
      });
      canvassplit = Split(['#frontcanvas', '#backcanvas'], {
        sizes: [50, 50],
        gutterSize: 5,
        onDragEnd: resizeAll
      });
      break;
    case 'left-right':
      document.getElementById("lr-btn").classList.add("depressed");
      document.getElementById("frontcanvas").style.display = "";
      document.getElementById("backcanvas").style.display = "";
      document.getElementById("bot").style.height = "calc(100% - 80px)";
      document.getElementById("bomdiv").classList.add("split-horizontal");
      document.getElementById("canvasdiv").classList.add("split-horizontal");
      document.getElementById("frontcanvas").classList.remove("split-horizontal");
      document.getElementById("backcanvas").classList.remove("split-horizontal");
      if (bomsplit) {
        bomsplit.destroy();
        bomsplit = null;
        canvassplit.destroy();
        canvassplit = null;
      }
      bomsplit = Split(['#bomdiv', '#canvasdiv'], {
        sizes: [50, 50],
        onDragEnd: resizeAll,
        gutterSize: 5
      });
      canvassplit = Split(['#frontcanvas', '#backcanvas'], {
        sizes: [50, 50],
        gutterSize: 5,
        direction: "vertical",
        onDragEnd: resizeAll
      });
  }
  settings.bomlayout = layout;
  writeStorage("bomlayout", layout);
  changeCanvasLayout(settings.canvaslayout);
}

function changeBomMode(mode) {
  document.getElementById("bom-grouped-btn").classList.remove("depressed");
  document.getElementById("bom-ungrouped-btn").classList.remove("depressed");
  document.getElementById("bom-netlist-btn").classList.remove("depressed");
  switch (mode) {
    case 'grouped':
      document.getElementById("bom-grouped-btn").classList.add("depressed");
      break;
    case 'ungrouped':
      document.getElementById("bom-ungrouped-btn").classList.add("depressed");
      break;
    case 'netlist':
      document.getElementById("bom-netlist-btn").classList.add("depressed");
  }
  writeStorage("bommode", mode);
  if (mode != settings.bommode) {
    settings.bommode = mode;
    bomSortFunction = null;
    currentSortColumn = null;
    currentSortOrder = null;
    clearHighlightedFootprints();
  }
  populateBomTable();
}

function focusFilterField() {
  focusInputField(document.getElementById("filter"));
}

function focusRefLookupField() {
  focusInputField(document.getElementById("reflookup"));
}

function toggleBomCheckbox(bomrowid, checkboxnum) {
  if (!bomrowid || checkboxnum > settings.checkboxes.length) {
    return;
  }
  var bomrow = document.getElementById(bomrowid);
  var checkbox = bomrow.childNodes[checkboxnum].childNodes[0];
  checkbox.checked = !checkbox.checked;
  checkbox.indeterminate = false;
  checkbox.onchange();
}

function checkBomCheckbox(bomrowid, checkboxname) {
  var checkboxnum = 0;
  while (checkboxnum < settings.checkboxes.length &&
    settings.checkboxes[checkboxnum].toLowerCase() != checkboxname.toLowerCase()) {
    checkboxnum++;
  }
  if (!bomrowid || checkboxnum >= settings.checkboxes.length) {
    return;
  }
  var bomrow = document.getElementById(bomrowid);
  var checkbox = bomrow.childNodes[checkboxnum + 1].childNodes[0];
  checkbox.checked = true;
  checkbox.indeterminate = false;
  checkbox.onchange();
}

function setBomCheckboxes(value) {
  writeStorage("bomCheckboxes", value);
  settings.checkboxes = value.split(",").filter((e) => e);
  prepCheckboxes();
  populateBomTable();
  populateDarkenWhenCheckedOptions();
}

function setDarkenWhenChecked(value) {
  writeStorage("darkenWhenChecked", value);
  settings.darkenWhenChecked = value;
  populateBomTable();
}

function prepCheckboxes() {
  var table = document.getElementById("checkbox-stats");
  while (table.childElementCount > 1) {
    table.removeChild(table.lastChild);
  }
  if (settings.checkboxes.length) {
    table.style.display = "";
  } else {
    table.style.display = "none";
  }
  for (var checkbox of settings.checkboxes) {
    var tr = document.createElement("TR");
    var td = document.createElement("TD");
    td.innerHTML = checkbox;
    tr.appendChild(td);
    td = document.createElement("TD");
    td.id = "checkbox-stats-" + checkbox;
    var progressbar = document.createElement("div");
    progressbar.classList.add("bar");
    td.appendChild(progressbar);
    var text = document.createElement("div");
    text.classList.add("text");
    td.appendChild(text);
    tr.appendChild(td);
    table.appendChild(tr);
    updateCheckboxStats(checkbox);
  }
}

function populateDarkenWhenCheckedOptions() {
  var container = document.getElementById("darkenWhenCheckedContainer");

  if (settings.checkboxes.length == 0) {
    container.parentElement.style.display = "none";
    return;
  }

  container.innerHTML = '';
  container.parentElement.style.display = "inline-block";

  function createOption(name, displayName) {
    var id = "darkenWhenChecked-" + name;

    var div = document.createElement("div");
    div.classList.add("radio-container");

    var input = document.createElement("input");
    input.type = "radio";
    input.name = "darkenWhenChecked";
    input.value = name;
    input.id = id;
    input.onchange = () => setDarkenWhenChecked(name);
    div.appendChild(input);

    // Preserve the selected element when the checkboxes change
    if (name == settings.darkenWhenChecked) {
      input.checked = true;
    }

    var label = document.createElement("label");
    label.innerHTML = displayName;
    label.htmlFor = id;
    div.appendChild(label);

    container.appendChild(div);
  }
  createOption("", "None");
  for (var checkbox of settings.checkboxes) {
    createOption(checkbox, checkbox);
  }
}

function updateCheckboxStats(checkbox) {
  var checked = getStoredCheckboxRefs(checkbox).size;
  var total = pcbdata.footprints.length - pcbdata.bom.skipped.length;
  var percent = checked * 100.0 / total;
  var td = document.getElementById("checkbox-stats-" + checkbox);
  td.firstChild.style.width = percent + "%";
  td.lastChild.innerHTML = checked + "/" + total + " (" + Math.round(percent) + "%)";
}

document.onkeydown = function(e) {
  switch (e.key) {
    case "n":
      if (document.activeElement.type == "text") {
        return;
      }
      if (currentHighlightedRowId !== null) {
        checkBomCheckbox(currentHighlightedRowId, "placed");
        highlightNextRow();
        e.preventDefault();
      }
      break;
    case "ArrowUp":
      highlightPreviousRow();
      e.preventDefault();
      break;
    case "ArrowDown":
      highlightNextRow();
      e.preventDefault();
      break;
    default:
      break;
  }
  if (e.altKey) {
    switch (e.key) {
      case "f":
        focusFilterField();
        e.preventDefault();
        break;
      case "r":
        focusRefLookupField();
        e.preventDefault();
        break;
      case "z":
        changeBomLayout("bom-only");
        e.preventDefault();
        break;
      case "x":
        changeBomLayout("left-right");
        e.preventDefault();
        break;
      case "c":
        changeBomLayout("top-bottom");
        e.preventDefault();
        break;
      case "v":
        changeCanvasLayout("F");
        e.preventDefault();
        break;
      case "b":
        changeCanvasLayout("FB");
        e.preventDefault();
        break;
      case "n":
        changeCanvasLayout("B");
        e.preventDefault();
        break;
      default:
        break;
    }
    if (e.key >= '1' && e.key <= '9') {
      toggleBomCheckbox(currentHighlightedRowId, parseInt(e.key));
    }
  }
}

function hideNetlistButton() {
  document.getElementById("bom-ungrouped-btn").classList.remove("middle-button");
  document.getElementById("bom-ungrouped-btn").classList.add("right-most-button");
  document.getElementById("bom-netlist-btn").style.display = "none";
}

window.onload = function(e) {
  initUtils();
  initRender();
  initStorage();
  initDefaults();
  cleanGutters();
  populateMetadata();
  dbgdiv = document.getElementById("dbg");
  bom = document.getElementById("bombody");
  bomhead = document.getElementById("bomhead");
  filter = "";
  reflookup = "";
  if (!("nets" in pcbdata)) {
    hideNetlistButton();
  }
  initDone = true;
  prepCheckboxes();
  // Triggers render
  changeBomLayout(settings.bomlayout);

  // Users may leave fullscreen without touching the checkbox. Uncheck.
  document.addEventListener('fullscreenchange', () => {
    if (!document.fullscreenElement)
      document.getElementById('fullscreenCheckbox').checked = false;
  });
}

window.onresize = resizeAll;
window.matchMedia("print").addListener(resizeAll);

///////////////////////////////////////////////

///////////////////////////////////////////////
 
///////////////////////////////////////////////
  </script>
</head>

<body>
<!-- USERHEADER -->
<div id="topmostdiv" class="topmostdiv">
  <div id="top">
    <div style="float: right; height: 100%;">
      <div class="hideonprint menu" style="float: right; top: 8px;">
        <button class="menubtn"></button>
        <div class="menu-content">
          <label class="menu-label menu-label-top" style="width: calc(50% - 18px)">
            <input id="darkmodeCheckbox" type="checkbox" onchange="setDarkMode(this.checked)">
            Dark mode
          </label><!-- This comment eats space! All of it!
          --><label class="menu-label menu-label-top" style="width: calc(50% - 17px); border-left: 0;">
            <input id="fullscreenCheckbox" type="checkbox" onchange="setFullscreen(this.checked)">
            Full Screen
          </label>
          <label class="menu-label" style="width: calc(50% - 18px)">
            <input id="fabricationCheckbox" type="checkbox" checked onchange="fabricationVisible(this.checked)">
            Fab layer
          </label><!-- This comment eats space! All of it!
          --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
            <input id="silkscreenCheckbox" type="checkbox" checked onchange="silkscreenVisible(this.checked)">
            Silkscreen
          </label>
          <label class="menu-label" style="width: calc(50% - 18px)">
            <input id="referencesCheckbox" type="checkbox" checked onchange="referencesVisible(this.checked)">
            References
          </label><!-- This comment eats space! All of it!
          --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
            <input id="valuesCheckbox" type="checkbox" checked onchange="valuesVisible(this.checked)">
            Values
          </label>
          <div id="tracksAndZonesCheckboxes">
            <label class="menu-label" style="width: calc(50% - 18px)">
              <input id="tracksCheckbox" type="checkbox" checked onchange="tracksVisible(this.checked)">
              Tracks
            </label><!-- This comment eats space! All of it!
            --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
              <input id="zonesCheckbox" type="checkbox" checked onchange="zonesVisible(this.checked)">
              Zones
            </label>
          </div>
          <label class="menu-label" style="width: calc(50% - 18px)">
            <input id="padsCheckbox" type="checkbox" checked onchange="padsVisible(this.checked)">
            Pads
          </label><!-- This comment eats space! All of it!
          --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
            <input id="dnpOutlineCheckbox" type="checkbox" checked onchange="dnpOutline(this.checked)">
            DNP outlined
          </label>
          <label class="menu-label">
            <input id="highlightpin1Checkbox" type="checkbox" onchange="setHighlightPin1(this.checked)">
            Highlight first pin
          </label>
          <label class="menu-label">
            <input id="dragCheckbox" type="checkbox" checked onchange="setRedrawOnDrag(this.checked)">
            Continuous redraw on drag
          </label>
          <label class="menu-label">
            <input id="crosshairCheckbox" type="checkbox" checked onchange="setShowCrosshair(this.checked)">
            Show Crosshair
          </label>
          <label class="menu-label">
            <span>Board rotation</span>
            <span style="float: right"><span id="rotationDegree">0</span>&#176;</span>
            <input id="boardRotation" type="range" min="-36" max="36" value="0" class="slider" oninput="setBoardRotation(this.value)">
          </label>
          <label class="menu-label">
            <div style="margin-left: 5px">Bom checkboxes</div>
            <input id="bomCheckboxes" class="menu-textbox" type=text
                   oninput="setBomCheckboxes(this.value)">
          </label>
          <label class="menu-label">
            <div style="margin-left: 5px">Darken when checked</div>
            <div id="darkenWhenCheckedContainer"></div>
          </label>
          <label class="menu-label">
            <span class="shameless-plug">
              <span>Created using</span>
              <a id="github-link" target="blank" href="https://github.com/openscopeproject/InteractiveHtmlBom">InteractiveHtmlBom</a>
            </span>
          </label>
        </div>
      </div>
      <div class="button-container hideonprint"
           style="float: right; position: relative; top: 8px">
        <button id="fl-btn" class="left-most-button" onclick="changeCanvasLayout('F')"
                title="Front only">F
        </button>
        <button id="fb-btn" class="middle-button" onclick="changeCanvasLayout('FB')"
                title="Front and Back">FB
        </button>
        <button id="bl-btn" class="right-most-button" onclick="changeCanvasLayout('B')"
                title="Back only">B
        </button>
      </div>
      <div class="button-container hideonprint"
           style="float: right; position: relative; top: 8px">
        <button id="bom-btn" class="left-most-button" onclick="changeBomLayout('bom-only')"
                title="BOM only"></button>
        <button id="lr-btn" class="middle-button" onclick="changeBomLayout('left-right')"
                title="BOM left, drawings right"></button>
        <button id="tb-btn" class="right-most-button" onclick="changeBomLayout('top-bottom')"
                title="BOM top, drawings bot"></button>
      </div>
      <div class="button-container hideonprint"
           style="float: right; position: relative; top: 8px">
        <button id="bom-grouped-btn" class="left-most-button" onclick="changeBomMode('grouped')"
                title="Grouped BOM"></button>
        <button id="bom-ungrouped-btn" class="middle-button" onclick="changeBomMode('ungrouped')"
                title="Ungrouped BOM"></button>
        <button id="bom-netlist-btn" class="right-most-button" onclick="changeBomMode('netlist')"
                title="Netlist"></button>
      </div>
      <div class="hideonprint menu" style="float: right; top: 8px;">
        <button class="statsbtn"></button>
        <div class="menu-content">
          <table class="stats">
            <tbody>
              <tr>
                <td width="40%">Board stats</td>
                <td>Front</td>
                <td>Back</td>
                <td>Total</td>
              </tr>
              <tr>
                <td>Components</td>
                <td id="stats-components-front">~</td>
                <td id="stats-components-back">~</td>
                <td id="stats-components-total">~</td>
              </tr>
              <tr>
                <td>Groups</td>
                <td id="stats-groups-front">~</td>
                <td id="stats-groups-back">~</td>
                <td id="stats-groups-total">~</td>
              </tr>
              <tr>
                <td>SMD pads</td>
                <td id="stats-smd-pads-front">~</td>
                <td id="stats-smd-pads-back">~</td>
                <td id="stats-smd-pads-total">~</td>
              </tr>
              <tr>
                <td>TH pads</td>
                <td colspan=3 id="stats-th-pads">~</td>
              </tr>
            </tbody>
          </table>
          <table class="stats">
            <col width="40%"/><col />
            <tbody id="checkbox-stats">
              <tr>
                <td colspan=2 style="border-top: 0">Checkboxes</td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
      <div class="hideonprint menu" style="float: right; top: 8px;">
        <button class="iobtn"></button>
        <div class="menu-content">
          <div class="menu-label menu-label-top">
            <div style="margin-left: 5px;">Save board image</div>
            <div class="flexbox">
              <input id="render-save-width" class="menu-textbox" type="text" value="1000" placeholder="Width"
                  style="flex-grow: 1; width: 50px;" oninput="validateSaveImgDimension(this)">
              <span>X</span>
              <input id="render-save-height" class="menu-textbox" type="text" value="1000" placeholder="Height"
                  style="flex-grow: 1; width: 50px;" oninput="validateSaveImgDimension(this)">
            </div>
            <label>
              <input id="render-save-transparent" type="checkbox">
              Transparent background
            </label>
            <div class="flexbox">
              <button class="savebtn" onclick="saveImage('F')">Front</button>
              <button class="savebtn" onclick="saveImage('B')">Back</button>
            </div>
          </div>
          <div class="menu-label">
            <span style="margin-left: 5px;">Config and checkbox state</span>
            <div class="flexbox">
              <button class="savebtn" onclick="saveSettings()">Export</button>
              <button class="savebtn" onclick="loadSettings()">Import</button>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div id="fileinfodiv" style="overflow: auto;">
      <table class="fileinfo">
        <tbody>
          <tr>
            <td id="title" class="title" style="width: 70%">
              Title
            </td>
            <td id="revision" class="title" style="width: 30%">
              Revision
            </td>
          </tr>
          <tr>
            <td id="company">
              Company
            </td>
            <td id="filedate">
              Date
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
  <div id="bot" class="split" style="height: calc(100% - 80px)">
    <div id="bomdiv" class="split split-horizontal">
      <div style="width: 100%">
        <input id="reflookup" class="textbox searchbox reflookup hideonprint" type="text" placeholder="Ref lookup"
               oninput="updateRefLookup(this.value)">
        <input id="filter" class="textbox searchbox filter hideonprint" type="text" placeholder="Filter"
               oninput="updateFilter(this.value)">
        <div class="button-container hideonprint" style="float: left; margin: 0;">
          <button id="copy" title="Copy bom table to clipboard"
               onclick="copyToClipboard()"></button>
        </div>
      </div>
      <div id="dbg"></div>
      <table class="bom">
        <thead id="bomhead">
        </thead>
        <tbody id="bombody">
        </tbody>
      </table>
    </div>
    <div id="canvasdiv" class="split split-horizontal">
      <div id="frontcanvas" class="split" touch-action="none" style="overflow: hidden">
        <div style="position: relative; width: 100%; height: 100%;">
          <canvas id="F_bg" style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
          <canvas id="F_fab" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
          <canvas id="F_slk" style="position: absolute; left: 0; top: 0; z-index: 2;"></canvas>
          <canvas id="F_hl" style="position: absolute; left: 0; top: 0; z-index: 3;"></canvas>
        </div>
      </div>
      <div id="backcanvas" class="split" touch-action="none" style="overflow: hidden">
        <div style="position: relative; width: 100%; height: 100%;">
          <canvas id="B_bg" style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
          <canvas id="B_fab" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
          <canvas id="B_slk" style="position: absolute; left: 0; top: 0; z-index: 2;"></canvas>
          <canvas id="B_hl" style="position: absolute; left: 0; top: 0; z-index: 3;"></canvas>
        </div>
      </div>
    </div>
  </div>
</div>
<!-- USERFOOTER -->
</body>

</html>
